From f6d65e533c62f6deb21342d4901ece24497b433e Mon Sep 17 00:00:00 2001 From: Pierre Schmitz Date: Thu, 4 Jun 2015 07:31:04 +0200 Subject: Update to MediaWiki 1.25.1 --- .../includes/api/format/ApiFormatDbgTest.php | 55 ++++++++ .../includes/api/format/ApiFormatDumpTest.php | 63 ++++++++++ .../includes/api/format/ApiFormatJsonTest.php | 106 ++++++++++++++-- .../includes/api/format/ApiFormatNoneTest.php | 38 +++++- .../includes/api/format/ApiFormatPhpTest.php | 139 ++++++++++++++++++++- .../includes/api/format/ApiFormatTestBase.php | 70 ++++++++--- .../includes/api/format/ApiFormatTxtTest.php | 55 ++++++++ .../includes/api/format/ApiFormatWddxTest.php | 74 +++++++++-- .../includes/api/format/ApiFormatXmlTest.php | 119 ++++++++++++++++++ 9 files changed, 673 insertions(+), 46 deletions(-) create mode 100644 tests/phpunit/includes/api/format/ApiFormatDbgTest.php create mode 100644 tests/phpunit/includes/api/format/ApiFormatDumpTest.php create mode 100644 tests/phpunit/includes/api/format/ApiFormatTxtTest.php create mode 100644 tests/phpunit/includes/api/format/ApiFormatXmlTest.php (limited to 'tests/phpunit/includes/api/format') diff --git a/tests/phpunit/includes/api/format/ApiFormatDbgTest.php b/tests/phpunit/includes/api/format/ApiFormatDbgTest.php new file mode 100644 index 00000000..3fcfc73f --- /dev/null +++ b/tests/phpunit/includes/api/format/ApiFormatDbgTest.php @@ -0,0 +1,55 @@ + \n array (\n 'dbg' => \n array (\n" . + " '*' => 'format=dbg has been deprecated. Please use format=json instead.',\n" . + " ),\n ),"; + + return array( + // Basic types + array( array( null ), "array ({$warning}\n 0 => NULL,\n)" ), + array( array( true ), "array ({$warning}\n 0 => '',\n)" ), + array( array( false ), "array ({$warning}\n)" ), + array( array( true, ApiResult::META_BC_BOOLS => array( 0 ) ), + "array ({$warning}\n 0 => true,\n)" ), + array( array( false, ApiResult::META_BC_BOOLS => array( 0 ) ), + "array ({$warning}\n 0 => false,\n)" ), + array( array( 42 ), "array ({$warning}\n 0 => 42,\n)" ), + array( array( 42.5 ), "array ({$warning}\n 0 => 42.5,\n)" ), + array( array( 1e42 ), "array ({$warning}\n 0 => 1.0E+42,\n)" ), + array( array( 'foo' ), "array ({$warning}\n 0 => 'foo',\n)" ), + array( array( 'fóo' ), "array ({$warning}\n 0 => 'fóo',\n)" ), + + // Arrays and objects + array( array( array() ), "array ({$warning}\n 0 => \n array (\n ),\n)" ), + array( array( array( 1 ) ), "array ({$warning}\n 0 => \n array (\n 0 => 1,\n ),\n)" ), + array( array( array( 'x' => 1 ) ), "array ({$warning}\n 0 => \n array (\n 'x' => 1,\n ),\n)" ), + array( array( array( 2 => 1 ) ), "array ({$warning}\n 0 => \n array (\n 2 => 1,\n ),\n)" ), + array( array( (object)array() ), "array ({$warning}\n 0 => \n array (\n ),\n)" ), + array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), "array ({$warning}\n 0 => \n array (\n 0 => 1,\n ),\n)" ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), "array ({$warning}\n 0 => \n array (\n 0 => 1,\n ),\n)" ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp' ) ), "array ({$warning}\n 0 => \n array (\n 'x' => 1,\n ),\n)" ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ), + "array ({$warning}\n 0 => \n array (\n 0 => \n array (\n 'key' => 'x',\n '*' => 1,\n ),\n ),\n)" ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), "array ({$warning}\n 0 => \n array (\n 'x' => 1,\n ),\n)" ), + array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), "array ({$warning}\n 0 => \n array (\n 0 => 'a',\n 1 => 'b',\n ),\n)" ), + + // Content + array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ), + "array ({$warning}\n '*' => 'foo',\n)" ), + + // BC Subelements + array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ), + "array ({$warning}\n 'foo' => \n array (\n '*' => 'foo',\n ),\n)" ), + ); + } + +} diff --git a/tests/phpunit/includes/api/format/ApiFormatDumpTest.php b/tests/phpunit/includes/api/format/ApiFormatDumpTest.php new file mode 100644 index 00000000..c0f67f8d --- /dev/null +++ b/tests/phpunit/includes/api/format/ApiFormatDumpTest.php @@ -0,0 +1,63 @@ + true ) ), + ); + } + + $warning = "\n [\"warnings\"]=>\n array(1) {\n [\"dump\"]=>\n array(1) {\n [\"*\"]=>\n" . + " string(64) \"format=dump has been deprecated. Please use format=json instead.\"\n" . + " }\n }"; + + return array( + // Basic types + array( array( null ), "array(2) {{$warning}\n [0]=>\n NULL\n}\n" ), + array( array( true ), "array(2) {{$warning}\n [0]=>\n string(0) \"\"\n}\n" ), + array( array( false ), "array(1) {{$warning}\n}\n" ), + array( array( true, ApiResult::META_BC_BOOLS => array( 0 ) ), + "array(2) {{$warning}\n [0]=>\n bool(true)\n}\n" ), + array( array( false, ApiResult::META_BC_BOOLS => array( 0 ) ), + "array(2) {{$warning}\n [0]=>\n bool(false)\n}\n" ), + array( array( 42 ), "array(2) {{$warning}\n [0]=>\n int(42)\n}\n" ), + array( array( 42.5 ), "array(2) {{$warning}\n [0]=>\n float(42.5)\n}\n" ), + array( array( 1e42 ), "array(2) {{$warning}\n [0]=>\n float(1.0E+42)\n}\n" ), + array( array( 'foo' ), "array(2) {{$warning}\n [0]=>\n string(3) \"foo\"\n}\n" ), + array( array( 'fóo' ), "array(2) {{$warning}\n [0]=>\n string(4) \"fóo\"\n}\n" ), + + // Arrays + array( array( array() ), "array(2) {{$warning}\n [0]=>\n array(0) {\n }\n}\n" ), + array( array( array( 1 ) ), "array(2) {{$warning}\n [0]=>\n array(1) {\n [0]=>\n int(1)\n }\n}\n" ), + array( array( array( 'x' => 1 ) ), "array(2) {{$warning}\n [0]=>\n array(1) {\n [\"x\"]=>\n int(1)\n }\n}\n" ), + array( array( array( 2 => 1 ) ), "array(2) {{$warning}\n [0]=>\n array(1) {\n [2]=>\n int(1)\n }\n}\n" ), + array( array( (object)array() ), "array(2) {{$warning}\n [0]=>\n array(0) {\n }\n}\n" ), + array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), "array(2) {{$warning}\n [0]=>\n array(1) {\n [0]=>\n int(1)\n }\n}\n" ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), "array(2) {{$warning}\n [0]=>\n array(1) {\n [0]=>\n int(1)\n }\n}\n" ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp' ) ), "array(2) {{$warning}\n [0]=>\n array(1) {\n [\"x\"]=>\n int(1)\n }\n}\n" ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ), + "array(2) {{$warning}\n [0]=>\n array(1) {\n [0]=>\n array(2) {\n [\"key\"]=>\n string(1) \"x\"\n [\"*\"]=>\n int(1)\n }\n }\n}\n" ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), "array(2) {{$warning}\n [0]=>\n array(1) {\n [\"x\"]=>\n int(1)\n }\n}\n" ), + array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), "array(2) {{$warning}\n [0]=>\n array(2) {\n [0]=>\n string(1) \"a\"\n [1]=>\n string(1) \"b\"\n }\n}\n" ), + + // Content + array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ), + "array(2) {{$warning}\n [\"*\"]=>\n string(3) \"foo\"\n}\n" ), + + // BC Subelements + array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ), + "array(2) {{$warning}\n [\"foo\"]=>\n array(1) {\n [\"*\"]=>\n string(3) \"foo\"\n }\n}\n" ), + ); + } + +} diff --git a/tests/phpunit/includes/api/format/ApiFormatJsonTest.php b/tests/phpunit/includes/api/format/ApiFormatJsonTest.php index fc1f9021..3dfcaf0f 100644 --- a/tests/phpunit/includes/api/format/ApiFormatJsonTest.php +++ b/tests/phpunit/includes/api/format/ApiFormatJsonTest.php @@ -2,21 +2,109 @@ /** * @group API - * @group Database - * @group medium * @covers ApiFormatJson */ class ApiFormatJsonTest extends ApiFormatTestBase { - public function testValidSyntax( ) { - $data = $this->apiRequest( 'json', array( 'action' => 'query', 'meta' => 'siteinfo' ) ); + protected $printerName = 'json'; - $this->assertInternalType( 'array', json_decode( $data, true ) ); - $this->assertGreaterThan( 0, count( (array)$data ) ); + private static function addFormatVersion( $format, $arr ) { + foreach ( $arr as &$p ) { + if ( !isset( $p[2] ) ) { + $p[2] = array( 'formatversion' => $format ); + } else { + $p[2]['formatversion'] = $format; + } + } + return $arr; } - public function testJsonpInjection( ) { - $data = $this->apiRequest( 'json', array( 'action' => 'query', 'meta' => 'siteinfo', 'callback' => 'myCallback' ) ); - $this->assertEquals( '/**/myCallback(', substr( $data, 0, 15 ) ); + public static function provideGeneralEncoding() { + return array_merge( + self::addFormatVersion( 1, array( + // Basic types + array( array( null ), '[null]' ), + array( array( true ), '[""]' ), + array( array( false ), '[]' ), + array( array( true, ApiResult::META_BC_BOOLS => array( 0 ) ), '[true]' ), + array( array( false, ApiResult::META_BC_BOOLS => array( 0 ) ), '[false]' ), + array( array( 42 ), '[42]' ), + array( array( 42.5 ), '[42.5]' ), + array( array( 1e42 ), '[1.0e+42]' ), + array( array( 'foo' ), '["foo"]' ), + array( array( 'fóo' ), '["f\u00f3o"]' ), + array( array( 'fóo' ), '["fóo"]', array( 'utf8' => 1 ) ), + + // Arrays and objects + array( array( array() ), '[[]]' ), + array( array( array( 1 ) ), '[[1]]' ), + array( array( array( 'x' => 1 ) ), '[{"x":1}]' ), + array( array( array( 2 => 1 ) ), '[{"2":1}]' ), + array( array( (object)array() ), '[{}]' ), + array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), '[{"0":1}]' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), '[[1]]' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp' ) ), '[{"x":1}]' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ), + '[[{"key":"x","*":1}]]' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), '[{"x":1}]' ), + array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), '[["a","b"]]' ), + + // Content + array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ), + '{"*":"foo"}' ), + + // BC Subelements + array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ), + '{"foo":{"*":"foo"}}' ), + + // Callbacks + array( array( 1 ), '/**/myCallback([1])', array( 'callback' => 'myCallback' ) ), + + // Cross-domain mangling + array( array( '< Cross-Domain-Policy >' ), '["\u003C Cross-Domain-Policy \u003E"]' ), + ) ), + self::addFormatVersion( 2, array( + // Basic types + array( array( null ), '[null]' ), + array( array( true ), '[true]' ), + array( array( false ), '[false]' ), + array( array( true, ApiResult::META_BC_BOOLS => array( 0 ) ), '[true]' ), + array( array( false, ApiResult::META_BC_BOOLS => array( 0 ) ), '[false]' ), + array( array( 42 ), '[42]' ), + array( array( 42.5 ), '[42.5]' ), + array( array( 1e42 ), '[1.0e+42]' ), + array( array( 'foo' ), '["foo"]' ), + array( array( 'fóo' ), '["fóo"]' ), + array( array( 'fóo' ), '["f\u00f3o"]', array( 'ascii' => 1 ) ), + + // Arrays and objects + array( array( array() ), '[[]]' ), + array( array( array( 'x' => 1 ) ), '[{"x":1}]' ), + array( array( array( 2 => 1 ) ), '[{"2":1}]' ), + array( array( (object)array() ), '[{}]' ), + array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), '[{"0":1}]' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), '[[1]]' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp' ) ), '[{"x":1}]' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ), + '[{"x":1}]' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), '[[1]]' ), + array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), '[{"0":"a","1":"b"}]' ), + + // Content + array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ), + '{"content":"foo"}' ), + + // BC Subelements + array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ), + '{"foo":"foo"}' ), + + // Callbacks + array( array( 1 ), '/**/myCallback([1])', array( 'callback' => 'myCallback' ) ), + + // Cross-domain mangling + array( array( '< Cross-Domain-Policy >' ), '["\u003C Cross-Domain-Policy \u003E"]' ), + ) ) + ); } + } diff --git a/tests/phpunit/includes/api/format/ApiFormatNoneTest.php b/tests/phpunit/includes/api/format/ApiFormatNoneTest.php index cabd750b..8f81a411 100644 --- a/tests/phpunit/includes/api/format/ApiFormatNoneTest.php +++ b/tests/phpunit/includes/api/format/ApiFormatNoneTest.php @@ -2,15 +2,43 @@ /** * @group API - * @group Database - * @group medium * @covers ApiFormatNone */ class ApiFormatNoneTest extends ApiFormatTestBase { - public function testValidSyntax( ) { - $data = $this->apiRequest( 'none', array( 'action' => 'query', 'meta' => 'siteinfo' ) ); + protected $printerName = 'none'; - $this->assertEquals( '', $data ); // No output! + public static function provideGeneralEncoding() { + return array( + // Basic types + array( array( null ), '' ), + array( array( true ), '' ), + array( array( false ), '' ), + array( array( 42 ), '' ), + array( array( 42.5 ), '' ), + array( array( 1e42 ), '' ), + array( array( 'foo' ), '' ), + array( array( 'fóo' ), '' ), + + // Arrays and objects + array( array( array() ), '' ), + array( array( array( 1 ) ), '' ), + array( array( array( 'x' => 1 ) ), '' ), + array( array( array( 2 => 1 ) ), '' ), + array( array( (object)array() ), '' ), + array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), '' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), '' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp' ) ), '' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ), '' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), '' ), + array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), '' ), + + // Content + array( array( '*' => 'foo' ), '' ), + + // BC Subelements + array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ), '' ), + ); } + } diff --git a/tests/phpunit/includes/api/format/ApiFormatPhpTest.php b/tests/phpunit/includes/api/format/ApiFormatPhpTest.php index 54f447a9..0cb44e92 100644 --- a/tests/phpunit/includes/api/format/ApiFormatPhpTest.php +++ b/tests/phpunit/includes/api/format/ApiFormatPhpTest.php @@ -2,16 +2,143 @@ /** * @group API - * @group Database - * @group medium * @covers ApiFormatPhp */ class ApiFormatPhpTest extends ApiFormatTestBase { - public function testValidSyntax( ) { - $data = $this->apiRequest( 'php', array( 'action' => 'query', 'meta' => 'siteinfo' ) ); + protected $printerName = 'php'; - $this->assertInternalType( 'array', unserialize( $data ) ); - $this->assertGreaterThan( 0, count( (array)$data ) ); + private static function addFormatVersion( $format, $arr ) { + foreach ( $arr as &$p ) { + if ( !isset( $p[2] ) ) { + $p[2] = array( 'formatversion' => $format ); + } else { + $p[2]['formatversion'] = $format; + } + } + return $arr; } + + public static function provideGeneralEncoding() { + return array_merge( + self::addFormatVersion( 1, array( + // Basic types + array( array( null ), 'a:1:{i:0;N;}' ), + array( array( true ), 'a:1:{i:0;s:0:"";}' ), + array( array( false ), 'a:0:{}' ), + array( array( true, ApiResult::META_BC_BOOLS => array( 0 ) ), + 'a:1:{i:0;b:1;}' ), + array( array( false, ApiResult::META_BC_BOOLS => array( 0 ) ), + 'a:1:{i:0;b:0;}' ), + array( array( 42 ), 'a:1:{i:0;i:42;}' ), + array( array( 42.5 ), 'a:1:{i:0;d:42.5;}' ), + array( array( 1e42 ), 'a:1:{i:0;d:1.0E+42;}' ), + array( array( 'foo' ), 'a:1:{i:0;s:3:"foo";}' ), + array( array( 'fóo' ), 'a:1:{i:0;s:4:"fóo";}' ), + + // Arrays and objects + array( array( array() ), 'a:1:{i:0;a:0:{}}' ), + array( array( array( 1 ) ), 'a:1:{i:0;a:1:{i:0;i:1;}}' ), + array( array( array( 'x' => 1 ) ), 'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ), + array( array( array( 2 => 1 ) ), 'a:1:{i:0;a:1:{i:2;i:1;}}' ), + array( array( (object)array() ), 'a:1:{i:0;a:0:{}}' ), + array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), 'a:1:{i:0;a:1:{i:0;i:1;}}' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), 'a:1:{i:0;a:1:{i:0;i:1;}}' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp' ) ), 'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ), + 'a:1:{i:0;a:1:{i:0;a:2:{s:3:"key";s:1:"x";s:1:"*";i:1;}}}' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), 'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ), + array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), 'a:1:{i:0;a:2:{i:0;s:1:"a";i:1;s:1:"b";}}' ), + + // Content + array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ), + 'a:1:{s:1:"*";s:3:"foo";}' ), + + // BC Subelements + array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ), + 'a:1:{s:3:"foo";a:1:{s:1:"*";s:3:"foo";}}' ), + ) ), + self::addFormatVersion( 2, array( + // Basic types + array( array( null ), 'a:1:{i:0;N;}' ), + array( array( true ), 'a:1:{i:0;b:1;}' ), + array( array( false ), 'a:1:{i:0;b:0;}' ), + array( array( true, ApiResult::META_BC_BOOLS => array( 0 ) ), + 'a:1:{i:0;b:1;}' ), + array( array( false, ApiResult::META_BC_BOOLS => array( 0 ) ), + 'a:1:{i:0;b:0;}' ), + array( array( 42 ), 'a:1:{i:0;i:42;}' ), + array( array( 42.5 ), 'a:1:{i:0;d:42.5;}' ), + array( array( 1e42 ), 'a:1:{i:0;d:1.0E+42;}' ), + array( array( 'foo' ), 'a:1:{i:0;s:3:"foo";}' ), + array( array( 'fóo' ), 'a:1:{i:0;s:4:"fóo";}' ), + + // Arrays and objects + array( array( array() ), 'a:1:{i:0;a:0:{}}' ), + array( array( array( 1 ) ), 'a:1:{i:0;a:1:{i:0;i:1;}}' ), + array( array( array( 'x' => 1 ) ), 'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ), + array( array( array( 2 => 1 ) ), 'a:1:{i:0;a:1:{i:2;i:1;}}' ), + array( array( (object)array() ), 'a:1:{i:0;a:0:{}}' ), + array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), 'a:1:{i:0;a:1:{i:0;i:1;}}' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), 'a:1:{i:0;a:1:{i:0;i:1;}}' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp' ) ), 'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ), + 'a:1:{i:0;a:1:{s:1:"x";i:1;}}' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), 'a:1:{i:0;a:1:{i:0;i:1;}}' ), + array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), 'a:1:{i:0;a:2:{i:0;s:1:"a";i:1;s:1:"b";}}' ), + + // Content + array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ), + 'a:1:{s:7:"content";s:3:"foo";}' ), + + // BC Subelements + array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ), + 'a:1:{s:3:"foo";s:3:"foo";}' ), + ) ) + ); + } + + public function testCrossDomainMangling() { + $config = new HashConfig( array( 'MangleFlashPolicy' => false ) ); + $context = new RequestContext; + $context->setConfig( new MultiConfig( array( + $config, + $context->getConfig(), + ) ) ); + $main = new ApiMain( $context ); + $main->getResult()->addValue( null, null, '< Cross-Domain-Policy >' ); + + if ( !function_exists( 'wfOutputHandler' ) ) { + function wfOutputHandler( $s ) { + return $s; + } + } + + $printer = $main->createPrinterByName( 'php' ); + ob_start( 'wfOutputHandler' ); + $printer->initPrinter(); + $printer->execute(); + $printer->closePrinter(); + $ret = ob_get_clean(); + $this->assertSame( 'a:1:{i:0;s:23:"< Cross-Domain-Policy >";}', $ret ); + + $config->set( 'MangleFlashPolicy', true ); + $printer = $main->createPrinterByName( 'php' ); + ob_start( 'wfOutputHandler' ); + try { + $printer->initPrinter(); + $printer->execute(); + $printer->closePrinter(); + ob_end_clean(); + $this->fail( 'Expected exception not thrown' ); + } catch ( UsageException $ex ) { + ob_end_clean(); + $this->assertSame( + 'This response cannot be represented using format=php. See https://bugzilla.wikimedia.org/show_bug.cgi?id=66776', + $ex->getMessage(), + 'Expected exception' + ); + } + } + } diff --git a/tests/phpunit/includes/api/format/ApiFormatTestBase.php b/tests/phpunit/includes/api/format/ApiFormatTestBase.php index 5f6d53ce..cabf62b1 100644 --- a/tests/phpunit/includes/api/format/ApiFormatTestBase.php +++ b/tests/phpunit/includes/api/format/ApiFormatTestBase.php @@ -1,32 +1,64 @@ createPrinterByName( $format ); - $printer->setUnescapeAmps( false ); + /** + * Return general data to be encoded for testing + * @return array See self::testGeneralEncoding + * @throws Exception + */ + public static function provideGeneralEncoding() { + throw new Exception( 'Subclass must implement ' . __METHOD__ ); + } - $printer->initPrinter( false ); + /** + * Get the formatter output for the given input data + * @param array $params Query parameters + * @param array $data Data to encode + * @param string $class Printer class to use instead of the normal one + * @return string + * @throws Exception + */ + protected function encodeData( array $params, array $data, $class = null ) { + $context = new RequestContext; + $context->setRequest( new FauxRequest( $params, true ) ); + $main = new ApiMain( $context ); + if ( $class !== null ) { + $main->getModuleManager()->addModule( $this->printerName, 'format', $class ); + } + $result = $main->getResult(); + $result->addArrayType( null, 'default' ); + foreach ( $data as $k => $v ) { + $result->addValue( null, $k, $v ); + } - ob_start(); + $printer = $main->createPrinterByName( $this->printerName ); + $printer->initPrinter(); $printer->execute(); - $out = ob_get_clean(); - - $printer->closePrinter(); + ob_start(); + try { + $printer->closePrinter(); + return ob_get_clean(); + } catch ( Exception $ex ) { + ob_end_clean(); + throw $ex; + } + } - return $out; + /** + * @dataProvider provideGeneralEncoding + */ + public function testGeneralEncoding( array $data, $expect, array $params = array() ) { + if ( isset( $params['SKIP'] ) ) { + $this->markTestSkipped( $expect ); + } + $this->assertSame( $expect, $this->encodeData( $params, $data ) ); } } diff --git a/tests/phpunit/includes/api/format/ApiFormatTxtTest.php b/tests/phpunit/includes/api/format/ApiFormatTxtTest.php new file mode 100644 index 00000000..b0a2a960 --- /dev/null +++ b/tests/phpunit/includes/api/format/ApiFormatTxtTest.php @@ -0,0 +1,55 @@ + Array\n (\n [txt] => Array\n (\n" . + " [*] => format=txt has been deprecated. Please use format=json instead.\n" . + " )\n\n )\n"; + + return array( + // Basic types + array( array( null ), "Array\n({$warning}\n [0] => \n)\n" ), + array( array( true ), "Array\n({$warning}\n [0] => \n)\n" ), + array( array( false ), "Array\n({$warning}\n)\n" ), + array( array( true, ApiResult::META_BC_BOOLS => array( 0 ) ), + "Array\n({$warning}\n [0] => 1\n)\n" ), + array( array( false, ApiResult::META_BC_BOOLS => array( 0 ) ), + "Array\n({$warning}\n [0] => \n)\n" ), + array( array( 42 ), "Array\n({$warning}\n [0] => 42\n)\n" ), + array( array( 42.5 ), "Array\n({$warning}\n [0] => 42.5\n)\n" ), + array( array( 1e42 ), "Array\n({$warning}\n [0] => 1.0E+42\n)\n" ), + array( array( 'foo' ), "Array\n({$warning}\n [0] => foo\n)\n" ), + array( array( 'fóo' ), "Array\n({$warning}\n [0] => fóo\n)\n" ), + + // Arrays and objects + array( array( array() ), "Array\n({$warning}\n [0] => Array\n (\n )\n\n)\n" ), + array( array( array( 1 ) ), "Array\n({$warning}\n [0] => Array\n (\n [0] => 1\n )\n\n)\n" ), + array( array( array( 'x' => 1 ) ), "Array\n({$warning}\n [0] => Array\n (\n [x] => 1\n )\n\n)\n" ), + array( array( array( 2 => 1 ) ), "Array\n({$warning}\n [0] => Array\n (\n [2] => 1\n )\n\n)\n" ), + array( array( (object)array() ), "Array\n({$warning}\n [0] => Array\n (\n )\n\n)\n" ), + array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), "Array\n({$warning}\n [0] => Array\n (\n [0] => 1\n )\n\n)\n" ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), "Array\n({$warning}\n [0] => Array\n (\n [0] => 1\n )\n\n)\n" ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp' ) ), "Array\n({$warning}\n [0] => Array\n (\n [x] => 1\n )\n\n)\n" ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ), + "Array\n({$warning}\n [0] => Array\n (\n [0] => Array\n (\n [key] => x\n [*] => 1\n )\n\n )\n\n)\n" ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), "Array\n({$warning}\n [0] => Array\n (\n [x] => 1\n )\n\n)\n" ), + array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), "Array\n({$warning}\n [0] => Array\n (\n [0] => a\n [1] => b\n )\n\n)\n" ), + + // Content + array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ), + "Array\n({$warning}\n [*] => foo\n)\n" ), + + // BC Subelements + array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ), + "Array\n({$warning}\n [foo] => Array\n (\n [*] => foo\n )\n\n)\n" ), + ); + } + +} diff --git a/tests/phpunit/includes/api/format/ApiFormatWddxTest.php b/tests/phpunit/includes/api/format/ApiFormatWddxTest.php index d075f547..07111300 100644 --- a/tests/phpunit/includes/api/format/ApiFormatWddxTest.php +++ b/tests/phpunit/includes/api/format/ApiFormatWddxTest.php @@ -2,19 +2,79 @@ /** * @group API - * @group Database - * @group medium * @covers ApiFormatWddx */ class ApiFormatWddxTest extends ApiFormatTestBase { + protected $printerName = 'wddx'; + + public static function provideGeneralEncoding() { + if ( ApiFormatWddx::useSlowPrinter() ) { + return array( + array( array(), 'Fast Wddx printer is unavailable', array( 'SKIP' => true ) ) + ); + } + return self::provideEncoding(); + } + + public static function provideEncoding() { + $p = '
format=wddx has been deprecated. Please use format=json instead.'; + $s = ''; + + return array( + // Basic types + array( array( null ), "{$p}{$s}" ), + array( array( true ), "{$p}{$s}" ), + array( array( false ), "{$p}{$s}" ), + array( array( true, ApiResult::META_BC_BOOLS => array( 0 ) ), + "{$p}{$s}" ), + array( array( false, ApiResult::META_BC_BOOLS => array( 0 ) ), + "{$p}{$s}" ), + array( array( 42 ), "{$p}42{$s}" ), + array( array( 42.5 ), "{$p}42.5{$s}" ), + array( array( 1e42 ), "{$p}1.0E+42{$s}" ), + array( array( 'foo' ), "{$p}foo{$s}" ), + array( array( 'fóo' ), "{$p}fóo{$s}" ), + + // Arrays and objects + array( array( array() ), "{$p}{$s}" ), + array( array( array( 1 ) ), "{$p}1{$s}" ), + array( array( array( 'x' => 1 ) ), "{$p}1{$s}" ), + array( array( array( 2 => 1 ) ), "{$p}1{$s}" ), + array( array( (object)array() ), "{$p}{$s}" ), + array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), "{$p}1{$s}" ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), "{$p}1{$s}" ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp' ) ), "{$p}1{$s}" ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ), + "{$p}x1{$s}" ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), "{$p}1{$s}" ), + array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), "{$p}ab{$s}" ), + + // Content + array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ), + "{$p}foo{$s}" ), + + // BC Subelements + array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ), + "{$p}foo{$s}" ), + ); + } + /** - * @requires function wddx_deserialize + * @dataProvider provideEncoding */ - public function testValidSyntax( ) { - $data = $this->apiRequest( 'wddx', array( 'action' => 'query', 'meta' => 'siteinfo' ) ); + public function testSlowEncoding( array $data, $expect, array $params = array() ) { + // Adjust expectation for differences between fast and slow printers. + $expect = str_replace( '\'', '"', $expect ); + $expect = str_replace( '/>', ' />', $expect ); + $expect = '' . $expect; + + $this->assertSame( $expect, $this->encodeData( $params, $data, 'ApiFormatWddxTest_SlowWddx' ) ); + } +} - $this->assertInternalType( 'array', wddx_deserialize( $data ) ); - $this->assertGreaterThan( 0, count( (array)$data ) ); +class ApiFormatWddxTest_SlowWddx extends ApiFormatWddx { + public static function useSlowPrinter() { + return true; } } diff --git a/tests/phpunit/includes/api/format/ApiFormatXmlTest.php b/tests/phpunit/includes/api/format/ApiFormatXmlTest.php new file mode 100644 index 00000000..7babaedb --- /dev/null +++ b/tests/phpunit/includes/api/format/ApiFormatXmlTest.php @@ -0,0 +1,119 @@ +doEditContent( new WikitextContent( + '' + ), 'Summary' ); + $page = WikiPage::factory( Title::newFromText( 'MediaWiki:ApiFormatXmlTest' ) ); + $page->doEditContent( new WikitextContent( 'Bogus' ), 'Summary' ); + $page = WikiPage::factory( Title::newFromText( 'ApiFormatXmlTest' ) ); + $page->doEditContent( new WikitextContent( 'Bogus' ), 'Summary' ); + } + + public static function provideGeneralEncoding() { + return array( + // Basic types + array( array( null, 'a' => null ), '<_v _idx="0" />' ), + array( array( true, 'a' => true ), '<_v _idx="0">true' ), + array( array( false, 'a' => false ), '<_v _idx="0">false' ), + array( array( true, 'a' => true, ApiResult::META_BC_BOOLS => array( 0, 'a' ) ), + '<_v _idx="0">1' ), + array( array( false, 'a' => false, ApiResult::META_BC_BOOLS => array( 0, 'a' ) ), + '<_v _idx="0">' ), + array( array( 42, 'a' => 42 ), '<_v _idx="0">42' ), + array( array( 42.5, 'a' => 42.5 ), '<_v _idx="0">42.5' ), + array( array( 1e42, 'a' => 1e42 ), '<_v _idx="0">1.0E+42' ), + array( array( 'foo', 'a' => 'foo' ), '<_v _idx="0">foo' ), + array( array( 'fóo', 'a' => 'fóo' ), '<_v _idx="0">fóo' ), + + // Arrays and objects + array( array( array() ), '<_v />' ), + array( array( array( 'x' => 1 ) ), '<_v x="1" />' ), + array( array( array( 2 => 1 ) ), '<_v><_v _idx="2">1' ), + array( array( (object)array() ), '<_v />' ), + array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), '<_v><_v _idx="0">1' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), '<_v><_v>1' ), + array( array( array( 'x' => 1, 'y' => array( 'z' => 1 ), ApiResult::META_TYPE => 'kvp' ) ), + '<_v><_v _name="x" xml:space="preserve">1<_v _name="y">1' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp', ApiResult::META_INDEXED_TAG_NAME => 'i', ApiResult::META_KVP_KEY_NAME => 'key' ) ), + '<_v>1' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ), + '<_v><_v key="x" xml:space="preserve">1' ), + array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), '<_v x="1" />' ), + array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), '<_v><_v _idx="0">a<_v _idx="1">b' ), + + // Content + array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ), + 'foo' ), + + // Specified element name + array( array( 'foo', 'bar', ApiResult::META_INDEXED_TAG_NAME => 'itn' ), + 'foobar' ), + + // Subelements + array( array( 'a' => 1, 's' => 1, '_subelements' => array( 's' ) ), + '1' ), + + // Content and subelement + array( array( 'a' => 1, 'content' => 'foo', ApiResult::META_CONTENT => 'content' ), + 'foo' ), + array( array( 's' => array(), 'content' => 'foo', ApiResult::META_CONTENT => 'content' ), + 'foo' ), + array( + array( + 's' => 1, + 'content' => 'foo', + ApiResult::META_CONTENT => 'content', + ApiResult::META_SUBELEMENTS => array( 's' ) + ), + '1foo' + ), + + // BC Subelements + array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ), + 'foo' ), + + // Name mangling + array( array( 'foo.bar' => 1 ), '' ), + array( array( '' => 1 ), '' ), + array( array( 'foo bar' => 1 ), '' ), + array( array( 'foo:bar' => 1 ), '' ), + array( array( 'foo%.bar' => 1 ), '' ), + array( array( '4foo' => 1, 'foo4' => 1 ), '' ), + array( array( "foo\xe3\x80\x80bar" => 1 ), '' ), + array( array( 'foo:bar' => 1, ApiResult::META_PRESERVE_KEYS => array( 'foo:bar' ) ), + '' ), + array( array( 'a', 'b', ApiResult::META_INDEXED_TAG_NAME => 'foo bar' ), + '<_foo.20.bar>a<_foo.20.bar>b' ), + + // includenamespace param + array( array( 'x' => 'foo' ), '', + array( 'includexmlnamespace' => 1 ) ), + + // xslt param + array( array(), 'Invalid or non-existent stylesheet specified', + array( 'xslt' => 'DoesNotExist' ) ), + array( array(), 'Stylesheet should be in the MediaWiki namespace.', + array( 'xslt' => 'ApiFormatXmlTest' ) ), + array( array(), 'Stylesheet should have .xsl extension.', + array( 'xslt' => 'MediaWiki:ApiFormatXmlTest' ) ), + array( array(), + 'getLocalURL( 'action=raw' ) ) . + '" type="text/xsl" ?>', + array( 'xslt' => 'MediaWiki:ApiFormatXmlTest.xsl' ) ), + ); + } + +} -- cgit v1.2.2