summaryrefslogtreecommitdiff
path: root/tests/phpunit/includes/api/format
diff options
context:
space:
mode:
Diffstat (limited to 'tests/phpunit/includes/api/format')
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatDbgTest.php55
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatDumpTest.php63
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatJsonTest.php106
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatNoneTest.php38
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatPhpTest.php139
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatTestBase.php70
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatTxtTest.php55
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatWddxTest.php74
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatXmlTest.php119
9 files changed, 673 insertions, 46 deletions
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 @@
+<?php
+
+/**
+ * @group API
+ * @covers ApiFormatDbg
+ */
+class ApiFormatDbgTest extends ApiFormatTestBase {
+
+ protected $printerName = 'dbg';
+
+ public static function provideGeneralEncoding() {
+ $warning = "\n 'warnings' => \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 @@
+<?php
+
+/**
+ * @group API
+ * @covers ApiFormatDump
+ */
+class ApiFormatDumpTest extends ApiFormatTestBase {
+
+ protected $printerName = 'dump';
+
+ public static function provideGeneralEncoding() {
+ // Sigh. Docs claim it's a boolean, but can have values 0, 1, or 2.
+ // Fortunately wfIniGetBool does the right thing.
+ if ( wfIniGetBool( 'xdebug.overload_var_dump' ) ) {
+ return array(
+ array( array(), 'Cannot test ApiFormatDump when xDebug overloads var_dump', array( 'SKIP' => 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 @@
<?php
-abstract class ApiFormatTestBase extends ApiTestCase {
+abstract class ApiFormatTestBase extends MediaWikiTestCase {
/**
- * @param string $format
- * @param array $params
- * @param array $data
- *
- * @return string
+ * Name of the formatter being tested
+ * @var string
*/
- protected function apiRequest( $format, $params, $data = null ) {
- $data = parent::doApiRequest( $params, $data, true );
-
- /** @var ApiMain $module */
- $module = $data[3];
+ protected $printerName;
- $printer = $module->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 @@
+<?php
+
+/**
+ * @group API
+ * @covers ApiFormatTxt
+ */
+class ApiFormatTxtTest extends ApiFormatTestBase {
+
+ protected $printerName = 'txt';
+
+ public static function provideGeneralEncoding() {
+ $warning = "\n [warnings] => 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 = '<wddxPacket version=\'1.0\'><header/><data><struct><var name=\'warnings\'><struct><var name=\'wddx\'><struct><var name=\'*\'><string>format=wddx has been deprecated. Please use format=json instead.</string></var></struct></var></struct></var>';
+ $s = '</struct></data></wddxPacket>';
+
+ return array(
+ // Basic types
+ array( array( null ), "{$p}<var name='0'><null/></var>{$s}" ),
+ array( array( true ), "{$p}<var name='0'><string></string></var>{$s}" ),
+ array( array( false ), "{$p}{$s}" ),
+ array( array( true, ApiResult::META_BC_BOOLS => array( 0 ) ),
+ "{$p}<var name='0'><boolean value='true'/></var>{$s}" ),
+ array( array( false, ApiResult::META_BC_BOOLS => array( 0 ) ),
+ "{$p}<var name='0'><boolean value='false'/></var>{$s}" ),
+ array( array( 42 ), "{$p}<var name='0'><number>42</number></var>{$s}" ),
+ array( array( 42.5 ), "{$p}<var name='0'><number>42.5</number></var>{$s}" ),
+ array( array( 1e42 ), "{$p}<var name='0'><number>1.0E+42</number></var>{$s}" ),
+ array( array( 'foo' ), "{$p}<var name='0'><string>foo</string></var>{$s}" ),
+ array( array( 'fóo' ), "{$p}<var name='0'><string>fóo</string></var>{$s}" ),
+
+ // Arrays and objects
+ array( array( array() ), "{$p}<var name='0'><array length='0'></array></var>{$s}" ),
+ array( array( array( 1 ) ), "{$p}<var name='0'><array length='1'><number>1</number></array></var>{$s}" ),
+ array( array( array( 'x' => 1 ) ), "{$p}<var name='0'><struct><var name='x'><number>1</number></var></struct></var>{$s}" ),
+ array( array( array( 2 => 1 ) ), "{$p}<var name='0'><struct><var name='2'><number>1</number></var></struct></var>{$s}" ),
+ array( array( (object)array() ), "{$p}<var name='0'><struct></struct></var>{$s}" ),
+ array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), "{$p}<var name='0'><struct><var name='0'><number>1</number></var></struct></var>{$s}" ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), "{$p}<var name='0'><array length='1'><number>1</number></array></var>{$s}" ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp' ) ), "{$p}<var name='0'><struct><var name='x'><number>1</number></var></struct></var>{$s}" ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ),
+ "{$p}<var name='0'><array length='1'><struct><var name='key'><string>x</string></var><var name='*'><number>1</number></var></struct></array></var>{$s}" ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), "{$p}<var name='0'><struct><var name='x'><number>1</number></var></struct></var>{$s}" ),
+ array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), "{$p}<var name='0'><array length='2'><string>a</string><string>b</string></array></var>{$s}" ),
+
+ // Content
+ array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ),
+ "{$p}<var name='*'><string>foo</string></var>{$s}" ),
+
+ // BC Subelements
+ array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ),
+ "{$p}<var name='foo'><struct><var name='*'><string>foo</string></var></struct></var>{$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 = '<?xml version="1.0"?>' . $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 @@
+<?php
+
+/**
+ * @group API
+ * @group Database
+ * @covers ApiFormatXml
+ */
+class ApiFormatXmlTest extends ApiFormatTestBase {
+
+ protected $printerName = 'xml';
+
+ public static function setUpBeforeClass() {
+ parent::setUpBeforeClass();
+ $page = WikiPage::factory( Title::newFromText( 'MediaWiki:ApiFormatXmlTest.xsl' ) );
+ $page->doEditContent( new WikitextContent(
+ '<?xml version="1.0"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" />'
+ ), '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 ), '<?xml version="1.0"?><api><_v _idx="0" /></api>' ),
+ array( array( true, 'a' => true ), '<?xml version="1.0"?><api a=""><_v _idx="0">true</_v></api>' ),
+ array( array( false, 'a' => false ), '<?xml version="1.0"?><api><_v _idx="0">false</_v></api>' ),
+ array( array( true, 'a' => true, ApiResult::META_BC_BOOLS => array( 0, 'a' ) ),
+ '<?xml version="1.0"?><api a=""><_v _idx="0">1</_v></api>' ),
+ array( array( false, 'a' => false, ApiResult::META_BC_BOOLS => array( 0, 'a' ) ),
+ '<?xml version="1.0"?><api><_v _idx="0"></_v></api>' ),
+ array( array( 42, 'a' => 42 ), '<?xml version="1.0"?><api a="42"><_v _idx="0">42</_v></api>' ),
+ array( array( 42.5, 'a' => 42.5 ), '<?xml version="1.0"?><api a="42.5"><_v _idx="0">42.5</_v></api>' ),
+ array( array( 1e42, 'a' => 1e42 ), '<?xml version="1.0"?><api a="1.0E+42"><_v _idx="0">1.0E+42</_v></api>' ),
+ array( array( 'foo', 'a' => 'foo' ), '<?xml version="1.0"?><api a="foo"><_v _idx="0">foo</_v></api>' ),
+ array( array( 'fóo', 'a' => 'fóo' ), '<?xml version="1.0"?><api a="fóo"><_v _idx="0">fóo</_v></api>' ),
+
+ // Arrays and objects
+ array( array( array() ), '<?xml version="1.0"?><api><_v /></api>' ),
+ array( array( array( 'x' => 1 ) ), '<?xml version="1.0"?><api><_v x="1" /></api>' ),
+ array( array( array( 2 => 1 ) ), '<?xml version="1.0"?><api><_v><_v _idx="2">1</_v></_v></api>' ),
+ array( array( (object)array() ), '<?xml version="1.0"?><api><_v /></api>' ),
+ array( array( array( 1, ApiResult::META_TYPE => 'assoc' ) ), '<?xml version="1.0"?><api><_v><_v _idx="0">1</_v></_v></api>' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'array' ) ), '<?xml version="1.0"?><api><_v><_v>1</_v></_v></api>' ),
+ array( array( array( 'x' => 1, 'y' => array( 'z' => 1 ), ApiResult::META_TYPE => 'kvp' ) ),
+ '<?xml version="1.0"?><api><_v><_v _name="x" xml:space="preserve">1</_v><_v _name="y"><z xml:space="preserve">1</z></_v></_v></api>' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'kvp', ApiResult::META_INDEXED_TAG_NAME => 'i', ApiResult::META_KVP_KEY_NAME => 'key' ) ),
+ '<?xml version="1.0"?><api><_v><i key="x" xml:space="preserve">1</i></_v></api>' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key' ) ),
+ '<?xml version="1.0"?><api><_v><_v key="x" xml:space="preserve">1</_v></_v></api>' ),
+ array( array( array( 'x' => 1, ApiResult::META_TYPE => 'BCarray' ) ), '<?xml version="1.0"?><api><_v x="1" /></api>' ),
+ array( array( array( 'a', 'b', ApiResult::META_TYPE => 'BCassoc' ) ), '<?xml version="1.0"?><api><_v><_v _idx="0">a</_v><_v _idx="1">b</_v></_v></api>' ),
+
+ // Content
+ array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ),
+ '<?xml version="1.0"?><api xml:space="preserve">foo</api>' ),
+
+ // Specified element name
+ array( array( 'foo', 'bar', ApiResult::META_INDEXED_TAG_NAME => 'itn' ),
+ '<?xml version="1.0"?><api><itn>foo</itn><itn>bar</itn></api>' ),
+
+ // Subelements
+ array( array( 'a' => 1, 's' => 1, '_subelements' => array( 's' ) ),
+ '<?xml version="1.0"?><api a="1"><s xml:space="preserve">1</s></api>' ),
+
+ // Content and subelement
+ array( array( 'a' => 1, 'content' => 'foo', ApiResult::META_CONTENT => 'content' ),
+ '<?xml version="1.0"?><api a="1" xml:space="preserve">foo</api>' ),
+ array( array( 's' => array(), 'content' => 'foo', ApiResult::META_CONTENT => 'content' ),
+ '<?xml version="1.0"?><api><s /><content xml:space="preserve">foo</content></api>' ),
+ array(
+ array(
+ 's' => 1,
+ 'content' => 'foo',
+ ApiResult::META_CONTENT => 'content',
+ ApiResult::META_SUBELEMENTS => array( 's' )
+ ),
+ '<?xml version="1.0"?><api><s xml:space="preserve">1</s><content xml:space="preserve">foo</content></api>'
+ ),
+
+ // BC Subelements
+ array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ),
+ '<?xml version="1.0"?><api><foo xml:space="preserve">foo</foo></api>' ),
+
+ // Name mangling
+ array( array( 'foo.bar' => 1 ), '<?xml version="1.0"?><api foo.bar="1" />' ),
+ array( array( '' => 1 ), '<?xml version="1.0"?><api _="1" />' ),
+ array( array( 'foo bar' => 1 ), '<?xml version="1.0"?><api _foo.20.bar="1" />' ),
+ array( array( 'foo:bar' => 1 ), '<?xml version="1.0"?><api _foo.3A.bar="1" />' ),
+ array( array( 'foo%.bar' => 1 ), '<?xml version="1.0"?><api _foo.25..2E.bar="1" />' ),
+ array( array( '4foo' => 1, 'foo4' => 1 ), '<?xml version="1.0"?><api _4foo="1" foo4="1" />' ),
+ array( array( "foo\xe3\x80\x80bar" => 1 ), '<?xml version="1.0"?><api _foo.3000.bar="1" />' ),
+ array( array( 'foo:bar' => 1, ApiResult::META_PRESERVE_KEYS => array( 'foo:bar' ) ),
+ '<?xml version="1.0"?><api foo:bar="1" />' ),
+ array( array( 'a', 'b', ApiResult::META_INDEXED_TAG_NAME => 'foo bar' ),
+ '<?xml version="1.0"?><api><_foo.20.bar>a</_foo.20.bar><_foo.20.bar>b</_foo.20.bar></api>' ),
+
+ // includenamespace param
+ array( array( 'x' => 'foo' ), '<?xml version="1.0"?><api x="foo" xmlns="http://www.mediawiki.org/xml/api/" />',
+ array( 'includexmlnamespace' => 1 ) ),
+
+ // xslt param
+ array( array(), '<?xml version="1.0"?><api><warnings><xml xml:space="preserve">Invalid or non-existent stylesheet specified</xml></warnings></api>',
+ array( 'xslt' => 'DoesNotExist' ) ),
+ array( array(), '<?xml version="1.0"?><api><warnings><xml xml:space="preserve">Stylesheet should be in the MediaWiki namespace.</xml></warnings></api>',
+ array( 'xslt' => 'ApiFormatXmlTest' ) ),
+ array( array(), '<?xml version="1.0"?><api><warnings><xml xml:space="preserve">Stylesheet should have .xsl extension.</xml></warnings></api>',
+ array( 'xslt' => 'MediaWiki:ApiFormatXmlTest' ) ),
+ array( array(),
+ '<?xml version="1.0"?><?xml-stylesheet href="' .
+ htmlspecialchars( Title::newFromText( 'MediaWiki:ApiFormatXmlTest.xsl' )->getLocalURL( 'action=raw' ) ) .
+ '" type="text/xsl" ?><api />',
+ array( 'xslt' => 'MediaWiki:ApiFormatXmlTest.xsl' ) ),
+ );
+ }
+
+}