aboutsummaryrefslogtreecommitdiffstats
path: root/tests/phpunit/includes/api
diff options
context:
space:
mode:
Diffstat (limited to 'tests/phpunit/includes/api')
-rw-r--r--tests/phpunit/includes/api/ApiContinuationManagerTest.php195
-rw-r--r--tests/phpunit/includes/api/ApiErrorFormatterTest.php343
-rw-r--r--tests/phpunit/includes/api/ApiMainTest.php2
-rw-r--r--tests/phpunit/includes/api/ApiMessageTest.php103
-rw-r--r--tests/phpunit/includes/api/ApiOptionsTest.php6
-rw-r--r--tests/phpunit/includes/api/ApiResultTest.php1446
-rw-r--r--tests/phpunit/includes/api/ApiTestCase.php2
-rw-r--r--tests/phpunit/includes/api/MockApi.php3
-rw-r--r--tests/phpunit/includes/api/MockApiQueryBase.php8
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatDbgTest.php23
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatDumpTest.php23
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatJsonTest.php122
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatNoneTest.php10
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatPhpTest.php101
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatTxtTest.php23
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatWddxTest.php23
-rw-r--r--tests/phpunit/includes/api/format/ApiFormatXmlTest.php114
17 files changed, 2432 insertions, 115 deletions
diff --git a/tests/phpunit/includes/api/ApiContinuationManagerTest.php b/tests/phpunit/includes/api/ApiContinuationManagerTest.php
new file mode 100644
index 000000000000..ea08c0284748
--- /dev/null
+++ b/tests/phpunit/includes/api/ApiContinuationManagerTest.php
@@ -0,0 +1,195 @@
+<?php
+
+/**
+ * @covers ApiContinuationManager
+ * @group API
+ */
+class ApiContinuationManagerTest extends MediaWikiTestCase {
+
+ private static function getManager( $continue, $allModules, $generatedModules ) {
+ $context = new DerivativeContext( RequestContext::getMain() );
+ $context->setRequest( new FauxRequest( array( 'continue' => $continue ) ) );
+ $main = new ApiMain( $context );
+ return new ApiContinuationManager( $main, $allModules, $generatedModules );
+ }
+
+ public function testContinuation() {
+ $allModules = array(
+ new MockApiQueryBase( 'mock1' ),
+ new MockApiQueryBase( 'mock2' ),
+ new MockApiQueryBase( 'mocklist' ),
+ );
+ $generator = new MockApiQueryBase( 'generator' );
+
+ $manager = self::getManager( '', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( 'ApiMain', $manager->getSource() );
+ $this->assertSame( false, $manager->isGeneratorDone() );
+ $this->assertSame( $allModules, $manager->getRunModules() );
+ $manager->addContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
+ $manager->addContinueParam( $allModules[2], 'mlcontinue', 2 );
+ $manager->addGeneratorContinueParam( $generator, 'gcontinue', 3 );
+ $this->assertSame( array( array(
+ 'mlcontinue' => 2,
+ 'm1continue' => '1|2',
+ 'continue' => '||mock2',
+ ), false ), $manager->getContinuation() );
+ $this->assertSame( array(
+ 'mock1' => array( 'm1continue' => '1|2' ),
+ 'mocklist' => array( 'mlcontinue' => 2 ),
+ 'generator' => array( 'gcontinue' => 3 ),
+ ), $manager->getRawContinuation() );
+
+ $result = new ApiResult( 0 );
+ $manager->setContinuationIntoResult( $result );
+ $this->assertSame( array(
+ 'mlcontinue' => 2,
+ 'm1continue' => '1|2',
+ 'continue' => '||mock2',
+ ), $result->getResultData( 'continue' ) );
+ $this->assertSame( null, $result->getResultData( 'batchcomplete' ) );
+
+ $manager = self::getManager( '', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( false, $manager->isGeneratorDone() );
+ $this->assertSame( $allModules, $manager->getRunModules() );
+ $manager->addContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
+ $manager->addGeneratorContinueParam( $generator, 'gcontinue', array( 3, 4 ) );
+ $this->assertSame( array( array(
+ 'm1continue' => '1|2',
+ 'continue' => '||mock2|mocklist',
+ ), false ), $manager->getContinuation() );
+ $this->assertSame( array(
+ 'mock1' => array( 'm1continue' => '1|2' ),
+ 'generator' => array( 'gcontinue' => '3|4' ),
+ ), $manager->getRawContinuation() );
+
+ $manager = self::getManager( '', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( false, $manager->isGeneratorDone() );
+ $this->assertSame( $allModules, $manager->getRunModules() );
+ $manager->addContinueParam( $allModules[2], 'mlcontinue', 2 );
+ $manager->addGeneratorContinueParam( $generator, 'gcontinue', 3 );
+ $this->assertSame( array( array(
+ 'mlcontinue' => 2,
+ 'gcontinue' => 3,
+ 'continue' => 'gcontinue||',
+ ), true ), $manager->getContinuation() );
+ $this->assertSame( array(
+ 'mocklist' => array( 'mlcontinue' => 2 ),
+ 'generator' => array( 'gcontinue' => 3 ),
+ ), $manager->getRawContinuation() );
+
+ $result = new ApiResult( 0 );
+ $manager->setContinuationIntoResult( $result );
+ $this->assertSame( array(
+ 'mlcontinue' => 2,
+ 'gcontinue' => 3,
+ 'continue' => 'gcontinue||',
+ ), $result->getResultData( 'continue' ) );
+ $this->assertSame( '', $result->getResultData( 'batchcomplete' ) );
+
+ $manager = self::getManager( '', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( false, $manager->isGeneratorDone() );
+ $this->assertSame( $allModules, $manager->getRunModules() );
+ $manager->addGeneratorContinueParam( $generator, 'gcontinue', 3 );
+ $this->assertSame( array( array(
+ 'gcontinue' => 3,
+ 'continue' => 'gcontinue||mocklist',
+ ), true ), $manager->getContinuation() );
+ $this->assertSame( array(
+ 'generator' => array( 'gcontinue' => 3 ),
+ ), $manager->getRawContinuation() );
+
+ $manager = self::getManager( '', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( false, $manager->isGeneratorDone() );
+ $this->assertSame( $allModules, $manager->getRunModules() );
+ $manager->addContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
+ $manager->addContinueParam( $allModules[2], 'mlcontinue', 2 );
+ $this->assertSame( array( array(
+ 'mlcontinue' => 2,
+ 'm1continue' => '1|2',
+ 'continue' => '||mock2',
+ ), false ), $manager->getContinuation() );
+ $this->assertSame( array(
+ 'mock1' => array( 'm1continue' => '1|2' ),
+ 'mocklist' => array( 'mlcontinue' => 2 ),
+ ), $manager->getRawContinuation() );
+
+ $manager = self::getManager( '', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( false, $manager->isGeneratorDone() );
+ $this->assertSame( $allModules, $manager->getRunModules() );
+ $manager->addContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
+ $this->assertSame( array( array(
+ 'm1continue' => '1|2',
+ 'continue' => '||mock2|mocklist',
+ ), false ), $manager->getContinuation() );
+ $this->assertSame( array(
+ 'mock1' => array( 'm1continue' => '1|2' ),
+ ), $manager->getRawContinuation() );
+
+ $manager = self::getManager( '', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( false, $manager->isGeneratorDone() );
+ $this->assertSame( $allModules, $manager->getRunModules() );
+ $manager->addContinueParam( $allModules[2], 'mlcontinue', 2 );
+ $this->assertSame( array( array(
+ 'mlcontinue' => 2,
+ 'continue' => '-||mock1|mock2',
+ ), true ), $manager->getContinuation() );
+ $this->assertSame( array(
+ 'mocklist' => array( 'mlcontinue' => 2 ),
+ ), $manager->getRawContinuation() );
+
+ $manager = self::getManager( '', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( false, $manager->isGeneratorDone() );
+ $this->assertSame( $allModules, $manager->getRunModules() );
+ $this->assertSame( array( array(), true ), $manager->getContinuation() );
+ $this->assertSame( array(), $manager->getRawContinuation() );
+
+ $manager = self::getManager( '||mock2', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( false, $manager->isGeneratorDone() );
+ $this->assertSame(
+ array_values( array_diff_key( $allModules, array( 1 => 1 ) ) ),
+ $manager->getRunModules()
+ );
+
+ $manager = self::getManager( '-||', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( true, $manager->isGeneratorDone() );
+ $this->assertSame(
+ array_values( array_diff_key( $allModules, array( 0 => 0, 1 => 1 ) ) ),
+ $manager->getRunModules()
+ );
+
+ try {
+ self::getManager( 'foo', $allModules, array( 'mock1', 'mock2' ) );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( UsageException $ex ) {
+ $this->assertSame(
+ 'Invalid continue param. You should pass the original value returned by the previous query',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ $manager = self::getManager( '||mock2', array_slice( $allModules, 0, 2 ), array( 'mock1', 'mock2' ) );
+ try {
+ $manager->addContinueParam( $allModules[1], 'm2continue', 1 );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( UnexpectedValueException $ex ) {
+ $this->assertSame(
+ 'Module \'mock2\' was not supposed to have been executed, but it was executed anyway',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ try {
+ $manager->addContinueParam( $allModules[2], 'mlcontinue', 1 );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( UnexpectedValueException $ex ) {
+ $this->assertSame(
+ 'Module \'mocklist\' called ApiContinuationManager::addContinueParam but was not passed to ApiContinuationManager::__construct',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ }
+
+}
diff --git a/tests/phpunit/includes/api/ApiErrorFormatterTest.php b/tests/phpunit/includes/api/ApiErrorFormatterTest.php
new file mode 100644
index 000000000000..344af62fddeb
--- /dev/null
+++ b/tests/phpunit/includes/api/ApiErrorFormatterTest.php
@@ -0,0 +1,343 @@
+<?php
+
+/**
+ * @group API
+ */
+class ApiErrorFormatterTest extends MediaWikiTestCase {
+
+ /**
+ * @covers ApiErrorFormatter
+ * @dataProvider provideErrorFormatter
+ */
+ public function testErrorFormatter( $format, $lang, $useDB,
+ $expect1, $expect2, $expect3
+ ) {
+ $result = new ApiResult( 8388608 );
+ $formatter = new ApiErrorFormatter( $result, Language::factory( $lang ), $format, $useDB );
+
+ $formatter->addWarning( 'string', 'mainpage' );
+ $formatter->addError( 'err', 'mainpage' );
+ $this->assertSame( $expect1, $result->getResultData(), 'Simple test' );
+
+ $result->reset();
+ $formatter->addWarning( 'foo', 'mainpage' );
+ $formatter->addWarning( 'foo', 'mainpage' );
+ $formatter->addWarning( 'foo', array( 'parentheses', 'foobar' ) );
+ $msg1 = wfMessage( 'mainpage' );
+ $formatter->addWarning( 'message', $msg1 );
+ $msg2 = new ApiMessage( 'mainpage', 'overriddenCode', array( 'overriddenData' => true ) );
+ $formatter->addWarning( 'messageWithData', $msg2 );
+ $formatter->addError( 'errWithData', $msg2 );
+ $this->assertSame( $expect2, $result->getResultData(), 'Complex test' );
+
+ $result->reset();
+ $status = Status::newGood();
+ $status->warning( 'mainpage' );
+ $status->warning( 'parentheses', 'foobar' );
+ $status->warning( $msg1 );
+ $status->warning( $msg2 );
+ $status->error( 'mainpage' );
+ $status->error( 'parentheses', 'foobar' );
+ $formatter->addMessagesFromStatus( 'status', $status );
+ $this->assertSame( $expect3, $result->getResultData(), 'Status test' );
+
+ $this->assertSame(
+ $expect3['errors']['status'],
+ $formatter->arrayFromStatus( $status, 'error' ),
+ 'arrayFromStatus test for error'
+ );
+ $this->assertSame(
+ $expect3['warnings']['status'],
+ $formatter->arrayFromStatus( $status, 'warning' ),
+ 'arrayFromStatus test for warning'
+ );
+ }
+
+ public static function provideErrorFormatter() {
+ $mainpagePlain = wfMessage( 'mainpage' )->useDatabase( false )->plain();
+ $parensPlain = wfMessage( 'parentheses', 'foobar' )->useDatabase( false )->plain();
+ $mainpageText = wfMessage( 'mainpage' )->inLanguage( 'de' )->text();
+ $parensText = wfMessage( 'parentheses', 'foobar' )->inLanguage( 'de' )->text();
+ $C = ApiResult::META_CONTENT;
+ $I = ApiResult::META_INDEXED_TAG_NAME;
+
+ return array(
+ array( 'wikitext', 'de', true,
+ array(
+ 'errors' => array(
+ 'err' => array(
+ array( 'code' => 'mainpage', 'text' => $mainpageText, $C => 'text' ),
+ $I => 'error',
+ ),
+ ),
+ 'warnings' => array(
+ 'string' => array(
+ array( 'code' => 'mainpage', 'text' => $mainpageText, $C => 'text' ),
+ $I => 'warning',
+ ),
+ ),
+ ),
+ array(
+ 'errors' => array(
+ 'errWithData' => array(
+ array( 'code' => 'overriddenCode', 'text' => $mainpageText,
+ 'overriddenData' => true, $C => 'text' ),
+ $I => 'error',
+ ),
+ ),
+ 'warnings' => array(
+ 'messageWithData' => array(
+ array( 'code' => 'overriddenCode', 'text' => $mainpageText,
+ 'overriddenData' => true, $C => 'text' ),
+ $I => 'warning',
+ ),
+ 'message' => array(
+ array( 'code' => 'mainpage', 'text' => $mainpageText, $C => 'text' ),
+ $I => 'warning',
+ ),
+ 'foo' => array(
+ array( 'code' => 'mainpage', 'text' => $mainpageText, $C => 'text' ),
+ array( 'code' => 'parentheses', 'text' => $parensText, $C => 'text' ),
+ $I => 'warning',
+ ),
+ ),
+ ),
+ array(
+ 'errors' => array(
+ 'status' => array(
+ array( 'code' => 'mainpage', 'text' => $mainpageText, $C => 'text' ),
+ array( 'code' => 'parentheses', 'text' => $parensText, $C => 'text' ),
+ $I => 'error',
+ ),
+ ),
+ 'warnings' => array(
+ 'status' => array(
+ array( 'code' => 'mainpage', 'text' => $mainpageText, $C => 'text' ),
+ array( 'code' => 'parentheses', 'text' => $parensText, $C => 'text' ),
+ array( 'code' => 'overriddenCode', 'text' => $mainpageText,
+ 'overriddenData' => true, $C => 'text' ),
+ $I => 'warning',
+ ),
+ ),
+ ),
+ ),
+ array( 'raw', 'fr', true,
+ array(
+ 'errors' => array(
+ 'err' => array(
+ array( 'code' => 'mainpage', 'message' => 'mainpage', 'params' => array( $I => 'param' ) ),
+ $I => 'error',
+ ),
+ ),
+ 'warnings' => array(
+ 'string' => array(
+ array( 'code' => 'mainpage', 'message' => 'mainpage', 'params' => array( $I => 'param' ) ),
+ $I => 'warning',
+ ),
+ ),
+ ),
+ array(
+ 'errors' => array(
+ 'errWithData' => array(
+ array( 'code' => 'overriddenCode', 'message' => 'mainpage', 'params' => array( $I => 'param' ),
+ 'overriddenData' => true ),
+ $I => 'error',
+ ),
+ ),
+ 'warnings' => array(
+ 'messageWithData' => array(
+ array( 'code' => 'overriddenCode', 'message' => 'mainpage', 'params' => array( $I => 'param' ),
+ 'overriddenData' => true ),
+ $I => 'warning',
+ ),
+ 'message' => array(
+ array( 'code' => 'mainpage', 'message' => 'mainpage', 'params' => array( $I => 'param' ) ),
+ $I => 'warning',
+ ),
+ 'foo' => array(
+ array( 'code' => 'mainpage', 'message' => 'mainpage', 'params' => array( $I => 'param' ) ),
+ array( 'code' => 'parentheses', 'message' => 'parentheses', 'params' => array( 'foobar', $I => 'param' ) ),
+ $I => 'warning',
+ ),
+ ),
+ ),
+ array(
+ 'errors' => array(
+ 'status' => array(
+ array( 'code' => 'mainpage', 'message' => 'mainpage', 'params' => array( $I => 'param' ) ),
+ array( 'code' => 'parentheses', 'message' => 'parentheses', 'params' => array( 'foobar', $I => 'param' ) ),
+ $I => 'error',
+ ),
+ ),
+ 'warnings' => array(
+ 'status' => array(
+ array( 'code' => 'mainpage', 'message' => 'mainpage', 'params' => array( $I => 'param' ) ),
+ array( 'code' => 'parentheses', 'message' => 'parentheses', 'params' => array( 'foobar', $I => 'param' ) ),
+ array( 'code' => 'overriddenCode', 'message' => 'mainpage', 'params' => array( $I => 'param' ),
+ 'overriddenData' => true ),
+ $I => 'warning',
+ ),
+ ),
+ ),
+ ),
+ array( 'none', 'fr', true,
+ array(
+ 'errors' => array(
+ 'err' => array(
+ array( 'code' => 'mainpage' ),
+ $I => 'error',
+ ),
+ ),
+ 'warnings' => array(
+ 'string' => array(
+ array( 'code' => 'mainpage' ),
+ $I => 'warning',
+ ),
+ ),
+ ),
+ array(
+ 'errors' => array(
+ 'errWithData' => array(
+ array( 'code' => 'overriddenCode', 'overriddenData' => true ),
+ $I => 'error',
+ ),
+ ),
+ 'warnings' => array(
+ 'messageWithData' => array(
+ array( 'code' => 'overriddenCode', 'overriddenData' => true ),
+ $I => 'warning',
+ ),
+ 'message' => array(
+ array( 'code' => 'mainpage' ),
+ $I => 'warning',
+ ),
+ 'foo' => array(
+ array( 'code' => 'mainpage' ),
+ array( 'code' => 'parentheses' ),
+ $I => 'warning',
+ ),
+ ),
+ ),
+ array(
+ 'errors' => array(
+ 'status' => array(
+ array( 'code' => 'mainpage' ),
+ array( 'code' => 'parentheses' ),
+ $I => 'error',
+ ),
+ ),
+ 'warnings' => array(
+ 'status' => array(
+ array( 'code' => 'mainpage' ),
+ array( 'code' => 'parentheses' ),
+ array( 'code' => 'overriddenCode', 'overriddenData' => true ),
+ $I => 'warning',
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+
+ /**
+ * @covers ApiErrorFormatter_BackCompat
+ */
+ public function testErrorFormatterBC() {
+ $mainpagePlain = wfMessage( 'mainpage' )->useDatabase( false )->plain();
+ $parensPlain = wfMessage( 'parentheses', 'foobar' )->useDatabase( false )->plain();
+
+ $result = new ApiResult( 8388608 );
+ $formatter = new ApiErrorFormatter_BackCompat( $result );
+
+ $formatter->addWarning( 'string', 'mainpage' );
+ $formatter->addError( 'err', 'mainpage' );
+ $this->assertSame( array(
+ 'error' => array(
+ 'code' => 'mainpage',
+ 'info' => $mainpagePlain,
+ ),
+ 'warnings' => array(
+ 'string' => array(
+ 'warnings' => $mainpagePlain,
+ ApiResult::META_CONTENT => 'warnings',
+ ),
+ ),
+ ), $result->getResultData(), 'Simple test' );
+
+ $result->reset();
+ $formatter->addWarning( 'foo', 'mainpage' );
+ $formatter->addWarning( 'foo', 'mainpage' );
+ $formatter->addWarning( 'foo', array( 'parentheses', 'foobar' ) );
+ $msg1 = wfMessage( 'mainpage' );
+ $formatter->addWarning( 'message', $msg1 );
+ $msg2 = new ApiMessage( 'mainpage', 'overriddenCode', array( 'overriddenData' => true ) );
+ $formatter->addWarning( 'messageWithData', $msg2 );
+ $formatter->addError( 'errWithData', $msg2 );
+ $this->assertSame( array(
+ 'error' => array(
+ 'code' => 'overriddenCode',
+ 'info' => $mainpagePlain,
+ 'overriddenData' => true,
+ ),
+ 'warnings' => array(
+ 'messageWithData' => array(
+ 'warnings' => $mainpagePlain,
+ ApiResult::META_CONTENT => 'warnings',
+ ),
+ 'message' => array(
+ 'warnings' => $mainpagePlain,
+ ApiResult::META_CONTENT => 'warnings',
+ ),
+ 'foo' => array(
+ 'warnings' => "$mainpagePlain\n$parensPlain",
+ ApiResult::META_CONTENT => 'warnings',
+ ),
+ ),
+ ), $result->getResultData(), 'Complex test' );
+
+ $result->reset();
+ $status = Status::newGood();
+ $status->warning( 'mainpage' );
+ $status->warning( 'parentheses', 'foobar' );
+ $status->warning( $msg1 );
+ $status->warning( $msg2 );
+ $status->error( 'mainpage' );
+ $status->error( 'parentheses', 'foobar' );
+ $formatter->addMessagesFromStatus( 'status', $status );
+ $this->assertSame( array(
+ 'error' => array(
+ 'code' => 'parentheses',
+ 'info' => $parensPlain,
+ ),
+ 'warnings' => array(
+ 'status' => array(
+ 'warnings' => "$mainpagePlain\n$parensPlain",
+ ApiResult::META_CONTENT => 'warnings',
+ ),
+ ),
+ ), $result->getResultData(), 'Status test' );
+
+ $I = ApiResult::META_INDEXED_TAG_NAME;
+ $this->assertSame(
+ array(
+ array( 'type' => 'error', 'message' => 'mainpage', 'params' => array( $I => 'param' ) ),
+ array( 'type' => 'error', 'message' => 'parentheses', 'params' => array( 'foobar', $I => 'param' ) ),
+ $I => 'error',
+ ),
+ $formatter->arrayFromStatus( $status, 'error' ),
+ 'arrayFromStatus test for error'
+ );
+ $this->assertSame(
+ array(
+ array( 'type' => 'warning', 'message' => 'mainpage', 'params' => array( $I => 'param' ) ),
+ array( 'type' => 'warning', 'message' => 'parentheses', 'params' => array( 'foobar', $I => 'param' ) ),
+ array( 'message' => 'mainpage', 'params' => array( $I => 'param' ), 'type' => 'warning' ),
+ array( 'message' => 'mainpage', 'params' => array( $I => 'param' ), 'type' => 'warning' ),
+ $I => 'warning',
+ ),
+ $formatter->arrayFromStatus( $status, 'warning' ),
+ 'arrayFromStatus test for warning'
+ );
+ }
+
+}
diff --git a/tests/phpunit/includes/api/ApiMainTest.php b/tests/phpunit/includes/api/ApiMainTest.php
index 7a03f7d27c8a..e8ef18049c85 100644
--- a/tests/phpunit/includes/api/ApiMainTest.php
+++ b/tests/phpunit/includes/api/ApiMainTest.php
@@ -16,7 +16,7 @@ class ApiMainTest extends ApiTestCase {
new FauxRequest( array( 'action' => 'query', 'meta' => 'siteinfo' ) )
);
$api->execute();
- $data = $api->getResultData();
+ $data = $api->getResult()->getResultData();
$this->assertInternalType( 'array', $data );
$this->assertArrayHasKey( 'query', $data );
}
diff --git a/tests/phpunit/includes/api/ApiMessageTest.php b/tests/phpunit/includes/api/ApiMessageTest.php
new file mode 100644
index 000000000000..6c3ce60d18df
--- /dev/null
+++ b/tests/phpunit/includes/api/ApiMessageTest.php
@@ -0,0 +1,103 @@
+<?php
+
+/**
+ * @group API
+ */
+class ApiMessageTest extends MediaWikiTestCase {
+
+ private function compareMessages( $msg, $msg2 ) {
+ $this->assertSame( $msg->getKey(), $msg2->getKey(), 'getKey' );
+ $this->assertSame( $msg->getKeysToTry(), $msg2->getKeysToTry(), 'getKeysToTry' );
+ $this->assertSame( $msg->getParams(), $msg2->getParams(), 'getParams' );
+ $this->assertSame( $msg->getFormat(), $msg2->getFormat(), 'getFormat' );
+ $this->assertSame( $msg->getLanguage(), $msg2->getLanguage(), 'getLanguage' );
+
+ $msg = TestingAccessWrapper::newFromObject( $msg );
+ $msg2 = TestingAccessWrapper::newFromObject( $msg2 );
+ foreach ( array( 'interface', 'useDatabase', 'title' ) as $key ) {
+ $this->assertSame( $msg->$key, $msg2->$key, $key );
+ }
+ }
+
+ /**
+ * @covers ApiMessage
+ */
+ public function testApiMessage() {
+ $msg = new Message( array( 'foo', 'bar' ), array( 'baz' ) );
+ $msg->inLanguage( 'de' )->title( Title::newMainPage() );
+ $msg2 = new ApiMessage( $msg, 'code', array( 'data' ) );
+ $this->compareMessages( $msg, $msg2 );
+ $this->assertEquals( 'code', $msg2->getApiCode() );
+ $this->assertEquals( array( 'data' ), $msg2->getApiData() );
+
+ $msg = new Message( array( 'foo', 'bar' ), array( 'baz' ) );
+ $msg2 = new ApiMessage( array( array( 'foo', 'bar' ), 'baz' ), 'code', array( 'data' ) );
+ $this->compareMessages( $msg, $msg2 );
+ $this->assertEquals( 'code', $msg2->getApiCode() );
+ $this->assertEquals( array( 'data' ), $msg2->getApiData() );
+
+ $msg = new Message( 'foo' );
+ $msg2 = new ApiMessage( 'foo' );
+ $this->compareMessages( $msg, $msg2 );
+ $this->assertEquals( 'foo', $msg2->getApiCode() );
+ $this->assertEquals( array(), $msg2->getApiData() );
+
+ $msg2->setApiCode( 'code', array( 'data' ) );
+ $this->assertEquals( 'code', $msg2->getApiCode() );
+ $this->assertEquals( array( 'data' ), $msg2->getApiData() );
+ $msg2->setApiCode( null );
+ $this->assertEquals( 'foo', $msg2->getApiCode() );
+ $this->assertEquals( array( 'data' ), $msg2->getApiData() );
+ $msg2->setApiData( array( 'data2' ) );
+ $this->assertEquals( array( 'data2' ), $msg2->getApiData() );
+ }
+
+ /**
+ * @covers ApiRawMessage
+ */
+ public function testApiRawMessage() {
+ $msg = new RawMessage( 'foo', array( 'baz' ) );
+ $msg->inLanguage( 'de' )->title( Title::newMainPage() );
+ $msg2 = new ApiRawMessage( $msg, 'code', array( 'data' ) );
+ $this->compareMessages( $msg, $msg2 );
+ $this->assertEquals( 'code', $msg2->getApiCode() );
+ $this->assertEquals( array( 'data' ), $msg2->getApiData() );
+
+ $msg = new RawMessage( 'foo', array( 'baz' ) );
+ $msg2 = new ApiRawMessage( array( 'foo', 'baz' ), 'code', array( 'data' ) );
+ $this->compareMessages( $msg, $msg2 );
+ $this->assertEquals( 'code', $msg2->getApiCode() );
+ $this->assertEquals( array( 'data' ), $msg2->getApiData() );
+
+ $msg = new RawMessage( 'foo' );
+ $msg2 = new ApiRawMessage( 'foo', 'code', array( 'data' ) );
+ $this->compareMessages( $msg, $msg2 );
+ $this->assertEquals( 'code', $msg2->getApiCode() );
+ $this->assertEquals( array( 'data' ), $msg2->getApiData() );
+
+ $msg2->setApiCode( 'code', array( 'data' ) );
+ $this->assertEquals( 'code', $msg2->getApiCode() );
+ $this->assertEquals( array( 'data' ), $msg2->getApiData() );
+ $msg2->setApiCode( null );
+ $this->assertEquals( 'foo', $msg2->getApiCode() );
+ $this->assertEquals( array( 'data' ), $msg2->getApiData() );
+ $msg2->setApiData( array( 'data2' ) );
+ $this->assertEquals( array( 'data2' ), $msg2->getApiData() );
+ }
+
+ /**
+ * @covers ApiMessage::create
+ */
+ public function testApiMessageCreate() {
+ $this->assertInstanceOf( 'ApiMessage', ApiMessage::create( new Message( 'mainpage' ) ) );
+ $this->assertInstanceOf( 'ApiRawMessage', ApiMessage::create( new RawMessage( 'mainpage' ) ) );
+ $this->assertInstanceOf( 'ApiMessage', ApiMessage::create( 'mainpage' ) );
+
+ $msg = new ApiMessage( 'mainpage' );
+ $this->assertSame( $msg, ApiMessage::create( $msg ) );
+
+ $msg = new ApiRawMessage( 'mainpage' );
+ $this->assertSame( $msg, ApiMessage::create( $msg ) );
+ }
+
+}
diff --git a/tests/phpunit/includes/api/ApiOptionsTest.php b/tests/phpunit/includes/api/ApiOptionsTest.php
index bd34018e3f58..51154ae39821 100644
--- a/tests/phpunit/includes/api/ApiOptionsTest.php
+++ b/tests/phpunit/includes/api/ApiOptionsTest.php
@@ -138,7 +138,7 @@ class ApiOptionsTest extends MediaWikiLangTestCase {
$this->mContext->setRequest( new FauxRequest( $request, true, $this->mSession ) );
$this->mTested->execute();
- return $this->mTested->getResult()->getData();
+ return $this->mTested->getResult()->getResultData( null, array( 'Strip' => 'all' ) );
}
/**
@@ -396,7 +396,7 @@ class ApiOptionsTest extends MediaWikiLangTestCase {
'options' => 'success',
'warnings' => array(
'options' => array(
- '*' => "Validation error for 'special': cannot be set by this module"
+ 'warnings' => "Validation error for 'special': cannot be set by this module"
)
)
), $response );
@@ -419,7 +419,7 @@ class ApiOptionsTest extends MediaWikiLangTestCase {
'options' => 'success',
'warnings' => array(
'options' => array(
- '*' => "Validation error for 'unknownOption': not a valid preference"
+ 'warnings' => "Validation error for 'unknownOption': not a valid preference"
)
)
), $response );
diff --git a/tests/phpunit/includes/api/ApiResultTest.php b/tests/phpunit/includes/api/ApiResultTest.php
new file mode 100644
index 000000000000..7e43a240a718
--- /dev/null
+++ b/tests/phpunit/includes/api/ApiResultTest.php
@@ -0,0 +1,1446 @@
+<?php
+
+/**
+ * @covers ApiResult
+ * @group API
+ */
+class ApiResultTest extends MediaWikiTestCase {
+
+ /**
+ * @covers ApiResult
+ */
+ public function testStaticDataMethods() {
+ $arr = array();
+
+ ApiResult::setValue( $arr, 'setValue', '1' );
+
+ ApiResult::setValue( $arr, null, 'unnamed 1' );
+ ApiResult::setValue( $arr, null, 'unnamed 2' );
+
+ ApiResult::setValue( $arr, 'deleteValue', '2' );
+ ApiResult::unsetValue( $arr, 'deleteValue' );
+
+ ApiResult::setContentValue( $arr, 'setContentValue', '3' );
+
+ $this->assertSame( array(
+ 'setValue' => '1',
+ 'unnamed 1',
+ 'unnamed 2',
+ ApiResult::META_CONTENT => 'setContentValue',
+ 'setContentValue' => '3',
+ ), $arr );
+
+ try {
+ ApiResult::setValue( $arr, 'setValue', '99' );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( RuntimeException $ex ) {
+ $this->assertSame(
+ 'Attempting to add element setValue=99, existing value is 1',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ try {
+ ApiResult::setContentValue( $arr, 'setContentValue2', '99' );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( RuntimeException $ex ) {
+ $this->assertSame(
+ 'Attempting to set content element as setContentValue2 when setContentValue ' .
+ 'is already set as the content element',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ ApiResult::setValue( $arr, 'setValue', '99', ApiResult::OVERRIDE );
+ $this->assertSame( '99', $arr['setValue'] );
+
+ ApiResult::setContentValue( $arr, 'setContentValue2', '99', ApiResult::OVERRIDE );
+ $this->assertSame( 'setContentValue2', $arr[ApiResult::META_CONTENT] );
+
+ $arr = array( 'foo' => 1, 'bar' => 1 );
+ ApiResult::setValue( $arr, 'top', '2', ApiResult::ADD_ON_TOP );
+ ApiResult::setValue( $arr, null, '2', ApiResult::ADD_ON_TOP );
+ ApiResult::setValue( $arr, 'bottom', '2' );
+ ApiResult::setValue( $arr, 'foo', '2', ApiResult::OVERRIDE );
+ ApiResult::setValue( $arr, 'bar', '2', ApiResult::OVERRIDE | ApiResult::ADD_ON_TOP );
+ $this->assertSame( array( 0, 'top', 'foo', 'bar', 'bottom' ), array_keys( $arr ) );
+
+ $arr = array();
+ ApiResult::setValue( $arr, 'sub', array( 'foo' => 1 ) );
+ ApiResult::setValue( $arr, 'sub', array( 'bar' => 1 ) );
+ $this->assertSame( array( 'sub' => array( 'foo' => 1, 'bar' => 1 ) ), $arr );
+
+ try {
+ ApiResult::setValue( $arr, 'sub', array( 'foo' => 2, 'baz' => 2 ) );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( RuntimeException $ex ) {
+ $this->assertSame(
+ 'Conflicting keys (foo) when attempting to merge element sub',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ $arr = array();
+ $title = Title::newFromText( "MediaWiki:Foobar" );
+ $obj = new stdClass;
+ $obj->foo = 1;
+ $obj->bar = 2;
+ ApiResult::setValue( $arr, 'title', $title );
+ ApiResult::setValue( $arr, 'obj', $obj );
+ $this->assertSame( array(
+ 'title' => (string)$title,
+ 'obj' => array( 'foo' => 1, 'bar' => 2, ApiResult::META_TYPE => 'assoc' ),
+ ), $arr );
+
+ $fh = tmpfile();
+ try {
+ ApiResult::setValue( $arr, 'file', $fh );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Cannot add resource(stream) to ApiResult',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ try {
+ $obj->file = $fh;
+ ApiResult::setValue( $arr, 'sub', $obj );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Cannot add resource(stream) to ApiResult',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ fclose( $fh );
+
+ try {
+ ApiResult::setValue( $arr, 'inf', INF );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Cannot add non-finite floats to ApiResult',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ try {
+ ApiResult::setValue( $arr, 'nan', NAN );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Cannot add non-finite floats to ApiResult',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ $arr = array();
+ $result2 = new ApiResult( 8388608 );
+ $result2->addValue( null, 'foo', 'bar' );
+ ApiResult::setValue( $arr, 'baz', $result2 );
+ $this->assertSame( array( 'baz' => array( 'foo' => 'bar' ) ), $arr );
+
+ $arr = array();
+ ApiResult::setValue( $arr, 'foo', "foo\x80bar" );
+ ApiResult::setValue( $arr, 'bar', "a\xcc\x81" );
+ ApiResult::setValue( $arr, 'baz', 74 );
+ $this->assertSame( array(
+ 'foo' => "foo\xef\xbf\xbdbar",
+ 'bar' => "\xc3\xa1",
+ 'baz' => 74,
+ ), $arr );
+ }
+
+ /**
+ * @covers ApiResult
+ */
+ public function testInstanceDataMethods() {
+ $result = new ApiResult( 8388608 );
+
+ $result->addValue( null, 'setValue', '1' );
+
+ $result->addValue( null, null, 'unnamed 1' );
+ $result->addValue( null, null, 'unnamed 2' );
+
+ $result->addValue( null, 'deleteValue', '2' );
+ $result->removeValue( null, 'deleteValue' );
+
+ $result->addValue( array( 'a', 'b' ), 'deleteValue', '3' );
+ $result->removeValue( array( 'a', 'b', 'deleteValue' ), null, '3' );
+
+ $result->addContentValue( null, 'setContentValue', '3' );
+
+ $this->assertSame( array(
+ 'setValue' => '1',
+ 'unnamed 1',
+ 'unnamed 2',
+ 'a' => array( 'b' => array() ),
+ 'setContentValue' => '3',
+ ApiResult::META_CONTENT => 'setContentValue',
+ ), $result->getResultData() );
+ $this->assertSame( 20, $result->getSize() );
+
+ try {
+ $result->addValue( null, 'setValue', '99' );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( RuntimeException $ex ) {
+ $this->assertSame(
+ 'Attempting to add element setValue=99, existing value is 1',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ try {
+ $result->addContentValue( null, 'setContentValue2', '99' );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( RuntimeException $ex ) {
+ $this->assertSame(
+ 'Attempting to set content element as setContentValue2 when setContentValue ' .
+ 'is already set as the content element',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ $result->addValue( null, 'setValue', '99', ApiResult::OVERRIDE );
+ $this->assertSame( '99', $result->getResultData( array( 'setValue' ) ) );
+
+ $result->addContentValue( null, 'setContentValue2', '99', ApiResult::OVERRIDE );
+ $this->assertSame( 'setContentValue2',
+ $result->getResultData( array( ApiResult::META_CONTENT ) ) );
+
+ $result->reset();
+ $this->assertSame( array(), $result->getResultData() );
+ $this->assertSame( 0, $result->getSize() );
+
+ $result->addValue( null, 'foo', 1 );
+ $result->addValue( null, 'bar', 1 );
+ $result->addValue( null, 'top', '2', ApiResult::ADD_ON_TOP );
+ $result->addValue( null, null, '2', ApiResult::ADD_ON_TOP );
+ $result->addValue( null, 'bottom', '2' );
+ $result->addValue( null, 'foo', '2', ApiResult::OVERRIDE );
+ $result->addValue( null, 'bar', '2', ApiResult::OVERRIDE | ApiResult::ADD_ON_TOP );
+ $this->assertSame( array( 0, 'top', 'foo', 'bar', 'bottom' ),
+ array_keys( $result->getResultData() ) );
+
+ $result->reset();
+ $result->addValue( null, 'foo', array( 'bar' => 1 ) );
+ $result->addValue( array( 'foo', 'top' ), 'x', 2, ApiResult::ADD_ON_TOP );
+ $result->addValue( array( 'foo', 'bottom' ), 'x', 2 );
+ $this->assertSame( array( 'top', 'bar', 'bottom' ),
+ array_keys( $result->getResultData( array( 'foo' ) ) ) );
+
+ $result->reset();
+ $result->addValue( null, 'sub', array( 'foo' => 1 ) );
+ $result->addValue( null, 'sub', array( 'bar' => 1 ) );
+ $this->assertSame( array( 'sub' => array( 'foo' => 1, 'bar' => 1 ) ),
+ $result->getResultData() );
+
+ try {
+ $result->addValue( null, 'sub', array( 'foo' => 2, 'baz' => 2 ) );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( RuntimeException $ex ) {
+ $this->assertSame(
+ 'Conflicting keys (foo) when attempting to merge element sub',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ $result->reset();
+ $title = Title::newFromText( "MediaWiki:Foobar" );
+ $obj = new stdClass;
+ $obj->foo = 1;
+ $obj->bar = 2;
+ $result->addValue( null, 'title', $title );
+ $result->addValue( null, 'obj', $obj );
+ $this->assertSame( array(
+ 'title' => (string)$title,
+ 'obj' => array( 'foo' => 1, 'bar' => 2, ApiResult::META_TYPE => 'assoc' ),
+ ), $result->getResultData() );
+
+ $fh = tmpfile();
+ try {
+ $result->addValue( null, 'file', $fh );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Cannot add resource(stream) to ApiResult',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ try {
+ $obj->file = $fh;
+ $result->addValue( null, 'sub', $obj );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Cannot add resource(stream) to ApiResult',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ fclose( $fh );
+
+ try {
+ $result->addValue( null, 'inf', INF );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Cannot add non-finite floats to ApiResult',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ try {
+ $result->addValue( null, 'nan', NAN );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Cannot add non-finite floats to ApiResult',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ $result->reset();
+ $result->addParsedLimit( 'foo', 12 );
+ $this->assertSame( array( 'limits' => array( 'foo' => 12 ) ), $result->getResultData() );
+ $result->addParsedLimit( 'foo', 13 );
+ $this->assertSame( array( 'limits' => array( 'foo' => 13 ) ), $result->getResultData() );
+ $this->assertSame( null, $result->getResultData( array( 'foo', 'bar', 'baz' ) ) );
+ $this->assertSame( 13, $result->getResultData( array( 'limits', 'foo' ) ) );
+ try {
+ $result->getResultData( array( 'limits', 'foo', 'bar' ) );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( InvalidArgumentException $ex ) {
+ $this->assertSame(
+ 'Path limits.foo is not an array',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ $result = new ApiResult( 10 );
+ $formatter = new ApiErrorFormatter( $result, Language::factory( 'en' ), 'none', false );
+ $result->setErrorFormatter( $formatter );
+ $this->assertFalse( $result->addValue( null, 'foo', '12345678901' ) );
+ $this->assertTrue( $result->addValue( null, 'foo', '12345678901', ApiResult::NO_SIZE_CHECK ) );
+ $this->assertSame( 0, $result->getSize() );
+ $result->reset();
+ $this->assertTrue( $result->addValue( null, 'foo', '1234567890' ) );
+ $this->assertFalse( $result->addValue( null, 'foo', '1' ) );
+ $result->removeValue( null, 'foo' );
+ $this->assertTrue( $result->addValue( null, 'foo', '1' ) );
+
+ $result = new ApiResult( 8388608 );
+ $result2 = new ApiResult( 8388608 );
+ $result2->addValue( null, 'foo', 'bar' );
+ $result->addValue( null, 'baz', $result2 );
+ $this->assertSame( array( 'baz' => array( 'foo' => 'bar' ) ), $result->getResultData() );
+
+ $result = new ApiResult( 8388608 );
+ $result->addValue( null, 'foo', "foo\x80bar" );
+ $result->addValue( null, 'bar', "a\xcc\x81" );
+ $result->addValue( null, 'baz', 74 );
+ $this->assertSame( array(
+ 'foo' => "foo\xef\xbf\xbdbar",
+ 'bar' => "\xc3\xa1",
+ 'baz' => 74,
+ ), $result->getResultData() );
+ }
+
+ /**
+ * @covers ApiResult
+ */
+ public function testMetadata() {
+ $arr = array( 'foo' => array( 'bar' => array() ) );
+ $result = new ApiResult( 8388608 );
+ $result->addValue( null, 'foo', array( 'bar' => array() ) );
+
+ $expect = array(
+ 'foo' => array(
+ 'bar' => array(
+ ApiResult::META_INDEXED_TAG_NAME => 'ritn',
+ ApiResult::META_TYPE => 'default',
+ ),
+ ApiResult::META_INDEXED_TAG_NAME => 'ritn',
+ ApiResult::META_TYPE => 'default',
+ ),
+ ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
+ ApiResult::META_INDEXED_TAG_NAME => 'itn',
+ ApiResult::META_PRESERVE_KEYS => array( 'foo', 'bar' ),
+ ApiResult::META_TYPE => 'array',
+ );
+
+ ApiResult::setSubelementsList( $arr, 'foo' );
+ ApiResult::setSubelementsList( $arr, array( 'bar', 'baz' ) );
+ ApiResult::unsetSubelementsList( $arr, 'baz' );
+ ApiResult::setIndexedTagNameRecursive( $arr, 'ritn' );
+ ApiResult::setIndexedTagName( $arr, 'itn' );
+ ApiResult::setPreserveKeysList( $arr, 'foo' );
+ ApiResult::setPreserveKeysList( $arr, array( 'bar', 'baz' ) );
+ ApiResult::unsetPreserveKeysList( $arr, 'baz' );
+ ApiResult::setArrayTypeRecursive( $arr, 'default' );
+ ApiResult::setArrayType( $arr, 'array' );
+ $this->assertSame( $expect, $arr );
+
+ $result->addSubelementsList( null, 'foo' );
+ $result->addSubelementsList( null, array( 'bar', 'baz' ) );
+ $result->removeSubelementsList( null, 'baz' );
+ $result->addIndexedTagNameRecursive( null, 'ritn' );
+ $result->addIndexedTagName( null, 'itn' );
+ $result->addPreserveKeysList( null, 'foo' );
+ $result->addPreserveKeysList( null, array( 'bar', 'baz' ) );
+ $result->removePreserveKeysList( null, 'baz' );
+ $result->addArrayTypeRecursive( null, 'default' );
+ $result->addArrayType( null, 'array' );
+ $this->assertSame( $expect, $result->getResultData() );
+
+ $arr = array( 'foo' => array( 'bar' => array() ) );
+ $expect = array(
+ 'foo' => array(
+ 'bar' => array(
+ ApiResult::META_TYPE => 'kvp',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ),
+ ApiResult::META_TYPE => 'kvp',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ),
+ ApiResult::META_TYPE => 'BCkvp',
+ ApiResult::META_KVP_KEY_NAME => 'bc',
+ );
+ ApiResult::setArrayTypeRecursive( $arr, 'kvp', 'key' );
+ ApiResult::setArrayType( $arr, 'BCkvp', 'bc' );
+ $this->assertSame( $expect, $arr );
+ }
+
+ /**
+ * @covers ApiResult
+ */
+ public function testUtilityFunctions() {
+ $arr = array(
+ 'foo' => array(
+ 'bar' => array( '_dummy' => 'foobaz' ),
+ 'bar2' => (object)array( '_dummy' => 'foobaz' ),
+ 'x' => 'ok',
+ '_dummy' => 'foobaz',
+ ),
+ 'foo2' => (object)array(
+ 'bar' => array( '_dummy' => 'foobaz' ),
+ 'bar2' => (object)array( '_dummy' => 'foobaz' ),
+ 'x' => 'ok',
+ '_dummy' => 'foobaz',
+ ),
+ ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
+ ApiResult::META_INDEXED_TAG_NAME => 'itn',
+ ApiResult::META_PRESERVE_KEYS => array( 'foo', 'bar', '_dummy2', 0 ),
+ ApiResult::META_TYPE => 'array',
+ '_dummy' => 'foobaz',
+ '_dummy2' => 'foobaz!',
+ );
+ $this->assertEquals( array(
+ 'foo' => array(
+ 'bar' => array(),
+ 'bar2' => (object)array(),
+ 'x' => 'ok',
+ ),
+ 'foo2' => (object)array(
+ 'bar' => array(),
+ 'bar2' => (object)array(),
+ 'x' => 'ok',
+ ),
+ '_dummy2' => 'foobaz!',
+ ), ApiResult::stripMetadata( $arr ), 'ApiResult::stripMetadata' );
+
+ $metadata = array();
+ $data = ApiResult::stripMetadataNonRecursive( $arr, $metadata );
+ $this->assertEquals( array(
+ 'foo' => array(
+ 'bar' => array( '_dummy' => 'foobaz' ),
+ 'bar2' => (object)array( '_dummy' => 'foobaz' ),
+ 'x' => 'ok',
+ '_dummy' => 'foobaz',
+ ),
+ 'foo2' => (object)array(
+ 'bar' => array( '_dummy' => 'foobaz' ),
+ 'bar2' => (object)array( '_dummy' => 'foobaz' ),
+ 'x' => 'ok',
+ '_dummy' => 'foobaz',
+ ),
+ '_dummy2' => 'foobaz!',
+ ), $data, 'ApiResult::stripMetadataNonRecursive ($data)' );
+ $this->assertEquals( array(
+ ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
+ ApiResult::META_INDEXED_TAG_NAME => 'itn',
+ ApiResult::META_PRESERVE_KEYS => array( 'foo', 'bar', '_dummy2', 0 ),
+ ApiResult::META_TYPE => 'array',
+ '_dummy' => 'foobaz',
+ ), $metadata, 'ApiResult::stripMetadataNonRecursive ($metadata)' );
+
+ $metadata = null;
+ $data = ApiResult::stripMetadataNonRecursive( (object)$arr, $metadata );
+ $this->assertEquals( (object)array(
+ 'foo' => array(
+ 'bar' => array( '_dummy' => 'foobaz' ),
+ 'bar2' => (object)array( '_dummy' => 'foobaz' ),
+ 'x' => 'ok',
+ '_dummy' => 'foobaz',
+ ),
+ 'foo2' => (object)array(
+ 'bar' => array( '_dummy' => 'foobaz' ),
+ 'bar2' => (object)array( '_dummy' => 'foobaz' ),
+ 'x' => 'ok',
+ '_dummy' => 'foobaz',
+ ),
+ '_dummy2' => 'foobaz!',
+ ), $data, 'ApiResult::stripMetadataNonRecursive on object ($data)' );
+ $this->assertEquals( array(
+ ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
+ ApiResult::META_INDEXED_TAG_NAME => 'itn',
+ ApiResult::META_PRESERVE_KEYS => array( 'foo', 'bar', '_dummy2', 0 ),
+ ApiResult::META_TYPE => 'array',
+ '_dummy' => 'foobaz',
+ ), $metadata, 'ApiResult::stripMetadataNonRecursive on object ($metadata)' );
+ }
+
+ /**
+ * @covers ApiResult
+ * @dataProvider provideTransformations
+ * @param string $label
+ * @param array $input
+ * @param array $transforms
+ * @param array|Exception $expect
+ */
+ public function testTransformations( $label, $input, $transforms, $expect ) {
+ $result = new ApiResult( false );
+ $result->addValue( null, 'test', $input );
+
+ if ( $expect instanceof Exception ) {
+ try {
+ $output = $result->getResultData( 'test', $transforms );
+ $this->fail( 'Expected exception not thrown', $label );
+ } catch ( Exception $ex ) {
+ $this->assertEquals( $ex, $expect, $label );
+ }
+ } else {
+ $output = $result->getResultData( 'test', $transforms );
+ $this->assertEquals( $expect, $output, $label );
+ }
+ }
+
+ public function provideTransformations() {
+ $kvp = function ( $keyKey, $key, $valKey, $value ) {
+ return array(
+ $keyKey => $key,
+ $valKey => $value,
+ ApiResult::META_PRESERVE_KEYS => array( $keyKey ),
+ ApiResult::META_CONTENT => $valKey,
+ ApiResult::META_TYPE => 'assoc',
+ );
+ };
+ $typeArr = array(
+ 'defaultArray' => array( 2 => 'a', 0 => 'b', 1 => 'c' ),
+ 'defaultAssoc' => array( 'x' => 'a', 1 => 'b', 0 => 'c' ),
+ 'defaultAssoc2' => array( 2 => 'a', 3 => 'b', 0 => 'c' ),
+ 'array' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'array' ),
+ 'BCarray' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'BCarray' ),
+ 'BCassoc' => array( 'a', 'b', 'c', ApiResult::META_TYPE => 'BCassoc' ),
+ 'assoc' => array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'kvp' => array( 'x' => 'a', 'y' => 'b', 'z' => array( 'c' ), ApiResult::META_TYPE => 'kvp' ),
+ 'BCkvp' => array( 'x' => 'a', 'y' => 'b',
+ ApiResult::META_TYPE => 'BCkvp',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ),
+ 'emptyDefault' => array( '_dummy' => 1 ),
+ 'emptyAssoc' => array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ),
+ '_dummy' => 1,
+ ApiResult::META_PRESERVE_KEYS => array( '_dummy' ),
+ );
+ $stripArr = array(
+ 'foo' => array(
+ 'bar' => array( '_dummy' => 'foobaz' ),
+ 'baz' => array(
+ ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
+ ApiResult::META_INDEXED_TAG_NAME => 'itn',
+ ApiResult::META_PRESERVE_KEYS => array( 'foo', 'bar', '_dummy2', 0 ),
+ ApiResult::META_TYPE => 'array',
+ ),
+ 'x' => 'ok',
+ '_dummy' => 'foobaz',
+ ),
+ ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
+ ApiResult::META_INDEXED_TAG_NAME => 'itn',
+ ApiResult::META_PRESERVE_KEYS => array( 'foo', 'bar', '_dummy2', 0 ),
+ ApiResult::META_TYPE => 'array',
+ '_dummy' => 'foobaz',
+ '_dummy2' => 'foobaz!',
+ );
+
+ return array(
+ array(
+ 'BC: META_BC_BOOLS',
+ array(
+ 'BCtrue' => true,
+ 'BCfalse' => false,
+ 'true' => true,
+ 'false' => false,
+ ApiResult::META_BC_BOOLS => array( 0, 'true', 'false' ),
+ ),
+ array( 'BC' => array() ),
+ array(
+ 'BCtrue' => '',
+ 'true' => true,
+ 'false' => false,
+ ApiResult::META_BC_BOOLS => array( 0, 'true', 'false' ),
+ )
+ ),
+ array(
+ 'BC: META_BC_SUBELEMENTS',
+ array(
+ 'bc' => 'foo',
+ 'nobc' => 'bar',
+ ApiResult::META_BC_SUBELEMENTS => array( 'bc' ),
+ ),
+ array( 'BC' => array() ),
+ array(
+ 'bc' => array(
+ '*' => 'foo',
+ ApiResult::META_CONTENT => '*',
+ ApiResult::META_TYPE => 'assoc',
+ ),
+ 'nobc' => 'bar',
+ ApiResult::META_BC_SUBELEMENTS => array( 'bc' ),
+ ),
+ ),
+ array(
+ 'BC: META_CONTENT',
+ array(
+ 'content' => '!!!',
+ ApiResult::META_CONTENT => 'content',
+ ),
+ array( 'BC' => array() ),
+ array(
+ '*' => '!!!',
+ ApiResult::META_CONTENT => '*',
+ ),
+ ),
+ array(
+ 'BC: BCkvp type',
+ array(
+ 'foo' => 'foo value',
+ 'bar' => 'bar value',
+ '_baz' => 'baz value',
+ ApiResult::META_TYPE => 'BCkvp',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ApiResult::META_PRESERVE_KEYS => array( '_baz' ),
+ ),
+ array( 'BC' => array() ),
+ array(
+ $kvp( 'key', 'foo', '*', 'foo value' ),
+ $kvp( 'key', 'bar', '*', 'bar value' ),
+ $kvp( 'key', '_baz', '*', 'baz value' ),
+ ApiResult::META_TYPE => 'array',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ApiResult::META_PRESERVE_KEYS => array( '_baz' ),
+ ),
+ ),
+ array(
+ 'BC: BCarray type',
+ array(
+ ApiResult::META_TYPE => 'BCarray',
+ ),
+ array( 'BC' => array() ),
+ array(
+ ApiResult::META_TYPE => 'default',
+ ),
+ ),
+ array(
+ 'BC: BCassoc type',
+ array(
+ ApiResult::META_TYPE => 'BCassoc',
+ ),
+ array( 'BC' => array() ),
+ array(
+ ApiResult::META_TYPE => 'default',
+ ),
+ ),
+ array(
+ 'BC: BCkvp exception',
+ array(
+ ApiResult::META_TYPE => 'BCkvp',
+ ),
+ array( 'BC' => array() ),
+ new UnexpectedValueException(
+ 'Type "BCkvp" used without setting ApiResult::META_KVP_KEY_NAME metadata item'
+ ),
+ ),
+ array(
+ 'BC: nobool, no*, nosub',
+ array(
+ 'true' => true,
+ 'false' => false,
+ 'content' => 'content',
+ ApiResult::META_CONTENT => 'content',
+ 'bc' => 'foo',
+ ApiResult::META_BC_SUBELEMENTS => array( 'bc' ),
+ 'BCarray' => array( ApiResult::META_TYPE => 'BCarray' ),
+ 'BCassoc' => array( ApiResult::META_TYPE => 'BCassoc' ),
+ 'BCkvp' => array(
+ 'foo' => 'foo value',
+ 'bar' => 'bar value',
+ '_baz' => 'baz value',
+ ApiResult::META_TYPE => 'BCkvp',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ApiResult::META_PRESERVE_KEYS => array( '_baz' ),
+ ),
+ ),
+ array( 'BC' => array( 'nobool', 'no*', 'nosub' ) ),
+ array(
+ 'true' => true,
+ 'false' => false,
+ 'content' => 'content',
+ 'bc' => 'foo',
+ 'BCarray' => array( ApiResult::META_TYPE => 'default' ),
+ 'BCassoc' => array( ApiResult::META_TYPE => 'default' ),
+ 'BCkvp' => array(
+ $kvp( 'key', 'foo', '*', 'foo value' ),
+ $kvp( 'key', 'bar', '*', 'bar value' ),
+ $kvp( 'key', '_baz', '*', 'baz value' ),
+ ApiResult::META_TYPE => 'array',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ApiResult::META_PRESERVE_KEYS => array( '_baz' ),
+ ),
+ ApiResult::META_CONTENT => 'content',
+ ApiResult::META_BC_SUBELEMENTS => array( 'bc' ),
+ ),
+ ),
+
+ array(
+ 'Types: Normal transform',
+ $typeArr,
+ array( 'Types' => array() ),
+ array(
+ 'defaultArray' => array( 'b', 'c', 'a', ApiResult::META_TYPE => 'array' ),
+ 'defaultAssoc' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'defaultAssoc2' => array( 2 => 'a', 3 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'array' => array( 'a', 'c', 'b', ApiResult::META_TYPE => 'array' ),
+ 'BCarray' => array( 'a', 'c', 'b', ApiResult::META_TYPE => 'array' ),
+ 'BCassoc' => array( 'a', 'b', 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'assoc' => array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'kvp' => array( 'x' => 'a', 'y' => 'b',
+ 'z' => array( 'c', ApiResult::META_TYPE => 'array' ),
+ ApiResult::META_TYPE => 'assoc'
+ ),
+ 'BCkvp' => array( 'x' => 'a', 'y' => 'b',
+ ApiResult::META_TYPE => 'assoc',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ),
+ 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ),
+ 'emptyAssoc' => array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ),
+ '_dummy' => 1,
+ ApiResult::META_PRESERVE_KEYS => array( '_dummy' ),
+ ApiResult::META_TYPE => 'assoc',
+ ),
+ ),
+ array(
+ 'Types: AssocAsObject',
+ $typeArr,
+ array( 'Types' => array( 'AssocAsObject' => true ) ),
+ (object)array(
+ 'defaultArray' => array( 'b', 'c', 'a', ApiResult::META_TYPE => 'array' ),
+ 'defaultAssoc' => (object)array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'defaultAssoc2' => (object)array( 2 => 'a', 3 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'array' => array( 'a', 'c', 'b', ApiResult::META_TYPE => 'array' ),
+ 'BCarray' => array( 'a', 'c', 'b', ApiResult::META_TYPE => 'array' ),
+ 'BCassoc' => (object)array( 'a', 'b', 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'assoc' => (object)array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'kvp' => (object)array( 'x' => 'a', 'y' => 'b',
+ 'z' => array( 'c', ApiResult::META_TYPE => 'array' ),
+ ApiResult::META_TYPE => 'assoc'
+ ),
+ 'BCkvp' => (object)array( 'x' => 'a', 'y' => 'b',
+ ApiResult::META_TYPE => 'assoc',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ),
+ 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ),
+ 'emptyAssoc' => (object)array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ),
+ '_dummy' => 1,
+ ApiResult::META_PRESERVE_KEYS => array( '_dummy' ),
+ ApiResult::META_TYPE => 'assoc',
+ ),
+ ),
+ array(
+ 'Types: ArmorKVP',
+ $typeArr,
+ array( 'Types' => array( 'ArmorKVP' => 'name' ) ),
+ array(
+ 'defaultArray' => array( 'b', 'c', 'a', ApiResult::META_TYPE => 'array' ),
+ 'defaultAssoc' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'defaultAssoc2' => array( 2 => 'a', 3 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'array' => array( 'a', 'c', 'b', ApiResult::META_TYPE => 'array' ),
+ 'BCarray' => array( 'a', 'c', 'b', ApiResult::META_TYPE => 'array' ),
+ 'BCassoc' => array( 'a', 'b', 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'assoc' => array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'kvp' => array(
+ $kvp( 'name', 'x', 'value', 'a' ),
+ $kvp( 'name', 'y', 'value', 'b' ),
+ $kvp( 'name', 'z', 'value', array( 'c', ApiResult::META_TYPE => 'array' ) ),
+ ApiResult::META_TYPE => 'array'
+ ),
+ 'BCkvp' => array(
+ $kvp( 'key', 'x', 'value', 'a' ),
+ $kvp( 'key', 'y', 'value', 'b' ),
+ ApiResult::META_TYPE => 'array',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ),
+ 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ),
+ 'emptyAssoc' => array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ),
+ '_dummy' => 1,
+ ApiResult::META_PRESERVE_KEYS => array( '_dummy' ),
+ ApiResult::META_TYPE => 'assoc',
+ ),
+ ),
+ array(
+ 'Types: ArmorKVP + BC',
+ $typeArr,
+ array( 'BC' => array(), 'Types' => array( 'ArmorKVP' => 'name' ) ),
+ array(
+ 'defaultArray' => array( 'b', 'c', 'a', ApiResult::META_TYPE => 'array' ),
+ 'defaultAssoc' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'defaultAssoc2' => array( 2 => 'a', 3 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'array' => array( 'a', 'c', 'b', ApiResult::META_TYPE => 'array' ),
+ 'BCarray' => array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'BCassoc' => array( 'a', 'b', 'c', ApiResult::META_TYPE => 'array' ),
+ 'assoc' => array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'kvp' => array(
+ $kvp( 'name', 'x', '*', 'a' ),
+ $kvp( 'name', 'y', '*', 'b' ),
+ $kvp( 'name', 'z', '*', array( 'c', ApiResult::META_TYPE => 'array' ) ),
+ ApiResult::META_TYPE => 'array'
+ ),
+ 'BCkvp' => array(
+ $kvp( 'key', 'x', '*', 'a' ),
+ $kvp( 'key', 'y', '*', 'b' ),
+ ApiResult::META_TYPE => 'array',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ),
+ 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ),
+ 'emptyAssoc' => array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ),
+ '_dummy' => 1,
+ ApiResult::META_PRESERVE_KEYS => array( '_dummy' ),
+ ApiResult::META_TYPE => 'assoc',
+ ),
+ ),
+ array(
+ 'Types: ArmorKVP + AssocAsObject',
+ $typeArr,
+ array( 'Types' => array( 'ArmorKVP' => 'name', 'AssocAsObject' => true ) ),
+ (object)array(
+ 'defaultArray' => array( 'b', 'c', 'a', ApiResult::META_TYPE => 'array' ),
+ 'defaultAssoc' => (object)array( 'x' => 'a', 1 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'defaultAssoc2' => (object)array( 2 => 'a', 3 => 'b', 0 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'array' => array( 'a', 'c', 'b', ApiResult::META_TYPE => 'array' ),
+ 'BCarray' => array( 'a', 'c', 'b', ApiResult::META_TYPE => 'array' ),
+ 'BCassoc' => (object)array( 'a', 'b', 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'assoc' => (object)array( 2 => 'a', 0 => 'b', 1 => 'c', ApiResult::META_TYPE => 'assoc' ),
+ 'kvp' => array(
+ (object)$kvp( 'name', 'x', 'value', 'a' ),
+ (object)$kvp( 'name', 'y', 'value', 'b' ),
+ (object)$kvp( 'name', 'z', 'value', array( 'c', ApiResult::META_TYPE => 'array' ) ),
+ ApiResult::META_TYPE => 'array'
+ ),
+ 'BCkvp' => array(
+ (object)$kvp( 'key', 'x', 'value', 'a' ),
+ (object)$kvp( 'key', 'y', 'value', 'b' ),
+ ApiResult::META_TYPE => 'array',
+ ApiResult::META_KVP_KEY_NAME => 'key',
+ ),
+ 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ),
+ 'emptyAssoc' => (object)array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ),
+ '_dummy' => 1,
+ ApiResult::META_PRESERVE_KEYS => array( '_dummy' ),
+ ApiResult::META_TYPE => 'assoc',
+ ),
+ ),
+ array(
+ 'Types: BCkvp exception',
+ array(
+ ApiResult::META_TYPE => 'BCkvp',
+ ),
+ array( 'Types' => array() ),
+ new UnexpectedValueException(
+ 'Type "BCkvp" used without setting ApiResult::META_KVP_KEY_NAME metadata item'
+ ),
+ ),
+
+ array(
+ 'Strip: With ArmorKVP + AssocAsObject transforms',
+ $typeArr,
+ array( 'Types' => array( 'ArmorKVP' => 'name', 'AssocAsObject' => true ), 'Strip' => 'all' ),
+ (object)array(
+ 'defaultArray' => array( 'b', 'c', 'a' ),
+ 'defaultAssoc' => (object)array( 'x' => 'a', 1 => 'b', 0 => 'c' ),
+ 'defaultAssoc2' => (object)array( 2 => 'a', 3 => 'b', 0 => 'c' ),
+ 'array' => array( 'a', 'c', 'b' ),
+ 'BCarray' => array( 'a', 'c', 'b' ),
+ 'BCassoc' => (object)array( 'a', 'b', 'c' ),
+ 'assoc' => (object)array( 2 => 'a', 0 => 'b', 1 => 'c' ),
+ 'kvp' => array(
+ (object)array( 'name' => 'x', 'value' => 'a' ),
+ (object)array( 'name' => 'y', 'value' => 'b' ),
+ (object)array( 'name' => 'z', 'value' => array( 'c' ) ),
+ ),
+ 'BCkvp' => array(
+ (object)array( 'key' => 'x', 'value' => 'a' ),
+ (object)array( 'key' => 'y', 'value' => 'b' ),
+ ),
+ 'emptyDefault' => array(),
+ 'emptyAssoc' => (object)array(),
+ '_dummy' => 1,
+ ),
+ ),
+
+ array(
+ 'Strip: all',
+ $stripArr,
+ array( 'Strip' => 'all' ),
+ array(
+ 'foo' => array(
+ 'bar' => array(),
+ 'baz' => array(),
+ 'x' => 'ok',
+ ),
+ '_dummy2' => 'foobaz!',
+ ),
+ ),
+ array(
+ 'Strip: base',
+ $stripArr,
+ array( 'Strip' => 'base' ),
+ array(
+ 'foo' => array(
+ 'bar' => array( '_dummy' => 'foobaz' ),
+ 'baz' => array(
+ ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
+ ApiResult::META_INDEXED_TAG_NAME => 'itn',
+ ApiResult::META_PRESERVE_KEYS => array( 'foo', 'bar', '_dummy2', 0 ),
+ ApiResult::META_TYPE => 'array',
+ ),
+ 'x' => 'ok',
+ '_dummy' => 'foobaz',
+ ),
+ '_dummy2' => 'foobaz!',
+ ),
+ ),
+ array(
+ 'Strip: bc',
+ $stripArr,
+ array( 'Strip' => 'bc' ),
+ array(
+ 'foo' => array(
+ 'bar' => array(),
+ 'baz' => array(
+ ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
+ ApiResult::META_INDEXED_TAG_NAME => 'itn',
+ ),
+ 'x' => 'ok',
+ ),
+ '_dummy2' => 'foobaz!',
+ ApiResult::META_SUBELEMENTS => array( 'foo', 'bar' ),
+ ApiResult::META_INDEXED_TAG_NAME => 'itn',
+ ),
+ ),
+
+ array(
+ 'Custom transform',
+ array(
+ 'foo' => '?',
+ 'bar' => '?',
+ '_dummy' => '?',
+ '_dummy2' => '?',
+ '_dummy3' => '?',
+ ApiResult::META_CONTENT => 'foo',
+ ApiResult::META_PRESERVE_KEYS => array( '_dummy2', '_dummy3' ),
+ ),
+ array(
+ 'Custom' => array( $this, 'customTransform' ),
+ 'BC' => array(),
+ 'Types' => array(),
+ 'Strip' => 'all'
+ ),
+ array(
+ '*' => 'FOO',
+ 'bar' => 'BAR',
+ 'baz' => array( 'a', 'b' ),
+ '_dummy2' => '_DUMMY2',
+ '_dummy3' => '_DUMMY3',
+ ApiResult::META_CONTENT => 'bar',
+ ),
+ ),
+ );
+
+ }
+
+ /**
+ * Custom transformer for testTransformations
+ * @param array &$data
+ * @param array &$metadata
+ */
+ public function customTransform( &$data, &$metadata ) {
+ // Prevent recursion
+ if ( isset( $metadata['_added'] ) ) {
+ $metadata[ApiResult::META_TYPE] = 'array';
+ return;
+ }
+
+ foreach ( $data as $k => $v ) {
+ $data[$k] = strtoupper( $k );
+ }
+ $data['baz'] = array( '_added' => 1, 'z' => 'b', 'y' => 'a' );
+ $metadata[ApiResult::META_PRESERVE_KEYS][0] = '_dummy';
+ $data[ApiResult::META_CONTENT] = 'bar';
+ }
+
+ /**
+ * @covers ApiResult
+ */
+ public function testDeprecatedFunctions() {
+ // Ignore ApiResult deprecation warnings during this test
+ set_error_handler( function ( $errno, $errstr ) use ( &$warnings ) {
+ if ( preg_match( '/Use of ApiResult::\S+ was deprecated in MediaWiki \d+.\d+\./', $errstr ) ) {
+ return true;
+ }
+ return false;
+ } );
+ $reset = new ScopedCallback( 'restore_error_handler' );
+
+ $context = new DerivativeContext( RequestContext::getMain() );
+ $context->setConfig( new HashConfig( array(
+ 'APIModules' => array(),
+ 'APIFormatModules' => array(),
+ 'APIMaxResultSize' => 42,
+ ) ) );
+ $main = new ApiMain( $context );
+ $result = TestingAccessWrapper::newFromObject( new ApiResult( $main ) );
+ $this->assertSame( 42, $result->maxSize );
+ $this->assertSame( $main->getErrorFormatter(), $result->errorFormatter );
+ $this->assertSame( $main, $result->mainForContinuation );
+
+ $result = new ApiResult( 8388608 );
+
+ $result->addContentValue( null, 'test', 'content' );
+ $result->addContentValue( array( 'foo', 'bar' ), 'test', 'content' );
+ $result->addIndexedTagName( null, 'itn' );
+ $result->addSubelementsList( null, array( 'sub' ) );
+ $this->assertSame( array(
+ 'foo' => array(
+ 'bar' => array(
+ '*' => 'content',
+ ),
+ ),
+ '*' => 'content',
+ ), $result->getData() );
+ $result->setRawMode();
+ $this->assertSame( array(
+ 'foo' => array(
+ 'bar' => array(
+ '*' => 'content',
+ ),
+ ),
+ '*' => 'content',
+ '_element' => 'itn',
+ '_subelements' => array( 'sub' ),
+ ), $result->getData() );
+
+ $arr = array();
+ ApiResult::setContent( $arr, 'value' );
+ ApiResult::setContent( $arr, 'value2', 'foobar' );
+ $this->assertSame( array(
+ ApiResult::META_CONTENT => 'content',
+ 'content' => 'value',
+ 'foobar' => array(
+ ApiResult::META_CONTENT => 'content',
+ 'content' => 'value2',
+ ),
+ ), $arr );
+
+ $result = new ApiResult( 3 );
+ $formatter = new ApiErrorFormatter_BackCompat( $result );
+ $result->setErrorFormatter( $formatter );
+ $result->disableSizeCheck();
+ $this->assertTrue( $result->addValue( null, 'foo', '1234567890' ) );
+ $result->enableSizeCheck();
+ $this->assertSame( 0, $result->getSize() );
+ $this->assertFalse( $result->addValue( null, 'foo', '1234567890' ) );
+
+ $arr = array( 'foo' => array( 'bar' => 1 ) );
+ $result->setIndexedTagName_recursive( $arr, 'itn' );
+ $this->assertSame( array(
+ 'foo' => array(
+ 'bar' => 1,
+ ApiResult::META_INDEXED_TAG_NAME => 'itn'
+ ),
+ ), $arr );
+
+ $status = Status::newGood();
+ $status->fatal( 'parentheses', '1' );
+ $status->fatal( 'parentheses', '2' );
+ $status->warning( 'parentheses', '3' );
+ $status->warning( 'parentheses', '4' );
+ $this->assertSame( array(
+ array(
+ 'type' => 'error',
+ 'message' => 'parentheses',
+ 'params' => array(
+ 0 => '1',
+ ApiResult::META_INDEXED_TAG_NAME => 'param',
+ ),
+ ),
+ array(
+ 'type' => 'error',
+ 'message' => 'parentheses',
+ 'params' => array(
+ 0 => '2',
+ ApiResult::META_INDEXED_TAG_NAME => 'param',
+ ),
+ ),
+ ApiResult::META_INDEXED_TAG_NAME => 'error',
+ ), $result->convertStatusToArray( $status, 'error' ) );
+ $this->assertSame( array(
+ array(
+ 'type' => 'warning',
+ 'message' => 'parentheses',
+ 'params' => array(
+ 0 => '3',
+ ApiResult::META_INDEXED_TAG_NAME => 'param',
+ ),
+ ),
+ array(
+ 'type' => 'warning',
+ 'message' => 'parentheses',
+ 'params' => array(
+ 0 => '4',
+ ApiResult::META_INDEXED_TAG_NAME => 'param',
+ ),
+ ),
+ ApiResult::META_INDEXED_TAG_NAME => 'warning',
+ ), $result->convertStatusToArray( $status, 'warning' ) );
+ }
+
+ /**
+ * @covers ApiResult
+ */
+ public function testDeprecatedContinuation() {
+ // Ignore ApiResult deprecation warnings during this test
+ set_error_handler( function ( $errno, $errstr ) use ( &$warnings ) {
+ if ( preg_match( '/Use of ApiResult::\S+ was deprecated in MediaWiki \d+.\d+\./', $errstr ) ) {
+ return true;
+ }
+ return false;
+ } );
+
+ $reset = new ScopedCallback( 'restore_error_handler' );
+ $allModules = array(
+ new MockApiQueryBase( 'mock1' ),
+ new MockApiQueryBase( 'mock2' ),
+ new MockApiQueryBase( 'mocklist' ),
+ );
+ $generator = new MockApiQueryBase( 'generator' );
+
+ $main = new ApiMain( RequestContext::getMain() );
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( array( false, $allModules ), $ret );
+ $result->setContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
+ $result->setContinueParam( $allModules[2], 'mlcontinue', 2 );
+ $result->setGeneratorContinueParam( $generator, 'gcontinue', 3 );
+ $result->endContinuation( 'raw' );
+ $result->endContinuation( 'standard' );
+ $this->assertSame( array(
+ 'mlcontinue' => 2,
+ 'm1continue' => '1|2',
+ 'continue' => '||mock2',
+ ), $result->getResultData( 'continue' ) );
+ $this->assertSame( null, $result->getResultData( 'batchcomplete' ) );
+ $this->assertSame( array(
+ 'mock1' => array( 'm1continue' => '1|2' ),
+ 'mocklist' => array( 'mlcontinue' => 2 ),
+ 'generator' => array( 'gcontinue' => 3 ),
+ ), $result->getResultData( 'query-continue' ) );
+ $main->setContinuationManager( null );
+
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( array( false, $allModules ), $ret );
+ $result->setContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
+ $result->setGeneratorContinueParam( $generator, 'gcontinue', array( 3, 4 ) );
+ $result->endContinuation( 'raw' );
+ $result->endContinuation( 'standard' );
+ $this->assertSame( array(
+ 'm1continue' => '1|2',
+ 'continue' => '||mock2|mocklist',
+ ), $result->getResultData( 'continue' ) );
+ $this->assertSame( null, $result->getResultData( 'batchcomplete' ) );
+ $this->assertSame( array(
+ 'mock1' => array( 'm1continue' => '1|2' ),
+ 'generator' => array( 'gcontinue' => '3|4' ),
+ ), $result->getResultData( 'query-continue' ) );
+ $main->setContinuationManager( null );
+
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( array( false, $allModules ), $ret );
+ $result->setContinueParam( $allModules[2], 'mlcontinue', 2 );
+ $result->setGeneratorContinueParam( $generator, 'gcontinue', 3 );
+ $result->endContinuation( 'raw' );
+ $result->endContinuation( 'standard' );
+ $this->assertSame( array(
+ 'mlcontinue' => 2,
+ 'gcontinue' => 3,
+ 'continue' => 'gcontinue||',
+ ), $result->getResultData( 'continue' ) );
+ $this->assertSame( '', $result->getResultData( 'batchcomplete' ) );
+ $this->assertSame( array(
+ 'mocklist' => array( 'mlcontinue' => 2 ),
+ 'generator' => array( 'gcontinue' => 3 ),
+ ), $result->getResultData( 'query-continue' ) );
+ $main->setContinuationManager( null );
+
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( array( false, $allModules ), $ret );
+ $result->setGeneratorContinueParam( $generator, 'gcontinue', 3 );
+ $result->endContinuation( 'raw' );
+ $result->endContinuation( 'standard' );
+ $this->assertSame( array(
+ 'gcontinue' => 3,
+ 'continue' => 'gcontinue||mocklist',
+ ), $result->getResultData( 'continue' ) );
+ $this->assertSame( '', $result->getResultData( 'batchcomplete' ) );
+ $this->assertSame( array(
+ 'generator' => array( 'gcontinue' => 3 ),
+ ), $result->getResultData( 'query-continue' ) );
+ $main->setContinuationManager( null );
+
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( array( false, $allModules ), $ret );
+ $result->setContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
+ $result->setContinueParam( $allModules[2], 'mlcontinue', 2 );
+ $result->endContinuation( 'raw' );
+ $result->endContinuation( 'standard' );
+ $this->assertSame( array(
+ 'mlcontinue' => 2,
+ 'm1continue' => '1|2',
+ 'continue' => '||mock2',
+ ), $result->getResultData( 'continue' ) );
+ $this->assertSame( null, $result->getResultData( 'batchcomplete' ) );
+ $this->assertSame( array(
+ 'mock1' => array( 'm1continue' => '1|2' ),
+ 'mocklist' => array( 'mlcontinue' => 2 ),
+ ), $result->getResultData( 'query-continue' ) );
+ $main->setContinuationManager( null );
+
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( array( false, $allModules ), $ret );
+ $result->setContinueParam( $allModules[0], 'm1continue', array( 1, 2 ) );
+ $result->endContinuation( 'raw' );
+ $result->endContinuation( 'standard' );
+ $this->assertSame( array(
+ 'm1continue' => '1|2',
+ 'continue' => '||mock2|mocklist',
+ ), $result->getResultData( 'continue' ) );
+ $this->assertSame( null, $result->getResultData( 'batchcomplete' ) );
+ $this->assertSame( array(
+ 'mock1' => array( 'm1continue' => '1|2' ),
+ ), $result->getResultData( 'query-continue' ) );
+ $main->setContinuationManager( null );
+
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( array( false, $allModules ), $ret );
+ $result->setContinueParam( $allModules[2], 'mlcontinue', 2 );
+ $result->endContinuation( 'raw' );
+ $result->endContinuation( 'standard' );
+ $this->assertSame( array(
+ 'mlcontinue' => 2,
+ 'continue' => '-||mock1|mock2',
+ ), $result->getResultData( 'continue' ) );
+ $this->assertSame( '', $result->getResultData( 'batchcomplete' ) );
+ $this->assertSame( array(
+ 'mocklist' => array( 'mlcontinue' => 2 ),
+ ), $result->getResultData( 'query-continue' ) );
+ $main->setContinuationManager( null );
+
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ $ret = $result->beginContinuation( null, $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame( array( false, $allModules ), $ret );
+ $result->endContinuation( 'raw' );
+ $result->endContinuation( 'standard' );
+ $this->assertSame( null, $result->getResultData( 'continue' ) );
+ $this->assertSame( '', $result->getResultData( 'batchcomplete' ) );
+ $this->assertSame( null, $result->getResultData( 'query-continue' ) );
+ $main->setContinuationManager( null );
+
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ $ret = $result->beginContinuation( '||mock2', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame(
+ array( false, array_values( array_diff_key( $allModules, array( 1 => 1 ) ) ) ),
+ $ret
+ );
+ $main->setContinuationManager( null );
+
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ $ret = $result->beginContinuation( '-||', $allModules, array( 'mock1', 'mock2' ) );
+ $this->assertSame(
+ array( true, array_values( array_diff_key( $allModules, array( 0 => 0, 1 => 1 ) ) ) ),
+ $ret
+ );
+ $main->setContinuationManager( null );
+
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ try {
+ $result->beginContinuation( 'foo', $allModules, array( 'mock1', 'mock2' ) );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( UsageException $ex ) {
+ $this->assertSame(
+ 'Invalid continue param. You should pass the original value returned by the previous query',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ $main->setContinuationManager( null );
+
+ $result = new ApiResult( 8388608 );
+ $result->setMainForContinuation( $main );
+ $result->beginContinuation( '||mock2', array_slice( $allModules, 0, 2 ), array( 'mock1', 'mock2' ) );
+ try {
+ $result->setContinueParam( $allModules[1], 'm2continue', 1 );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( UnexpectedValueException $ex ) {
+ $this->assertSame(
+ 'Module \'mock2\' was not supposed to have been executed, but it was executed anyway',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ try {
+ $result->setContinueParam( $allModules[2], 'mlcontinue', 1 );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( UnexpectedValueException $ex ) {
+ $this->assertSame(
+ 'Module \'mocklist\' called ApiContinuationManager::addContinueParam but was not passed to ApiContinuationManager::__construct',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+ $main->setContinuationManager( null );
+
+ }
+
+ public function testObjectSerialization() {
+ $arr = array();
+ ApiResult::setValue( $arr, 'foo', (object)array( 'a' => 1, 'b' => 2 ) );
+ $this->assertSame( array(
+ 'a' => 1,
+ 'b' => 2,
+ ApiResult::META_TYPE => 'assoc',
+ ), $arr['foo'] );
+
+ $arr = array();
+ ApiResult::setValue( $arr, 'foo', new ApiResultTestStringifiableObject() );
+ $this->assertSame( 'Ok', $arr['foo'] );
+
+ $arr = array();
+ ApiResult::setValue( $arr, 'foo', new ApiResultTestSerializableObject( 'Ok' ) );
+ $this->assertSame( 'Ok', $arr['foo'] );
+
+ try {
+ $arr = array();
+ ApiResult::setValue( $arr, 'foo', new ApiResultTestSerializableObject(
+ new ApiResultTestStringifiableObject()
+ ) );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( UnexpectedValueException $ex ) {
+ $this->assertSame(
+ 'ApiResultTestSerializableObject::serializeForApiResult() returned an object of class ApiResultTestStringifiableObject',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ try {
+ $arr = array();
+ ApiResult::setValue( $arr, 'foo', new ApiResultTestSerializableObject( NAN ) );
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( UnexpectedValueException $ex ) {
+ $this->assertSame(
+ 'ApiResultTestSerializableObject::serializeForApiResult() returned an invalid value: Cannot add non-finite floats to ApiResult',
+ $ex->getMessage(),
+ 'Expected exception'
+ );
+ }
+
+ $arr = array();
+ ApiResult::setValue( $arr, 'foo', new ApiResultTestSerializableObject(
+ array(
+ 'one' => new ApiResultTestStringifiableObject( '1' ),
+ 'two' => new ApiResultTestSerializableObject( 2 ),
+ )
+ ) );
+ $this->assertSame( array(
+ 'one' => '1',
+ 'two' => 2,
+ ), $arr['foo'] );
+ }
+
+}
+
+class ApiResultTestStringifiableObject {
+ private $ret;
+
+ public function __construct( $ret = 'Ok' ) {
+ $this->ret = $ret;
+ }
+
+ public function __toString() {
+ return $this->ret;
+ }
+}
+
+class ApiResultTestSerializableObject {
+ private $ret;
+
+ public function __construct( $ret ) {
+ $this->ret = $ret;
+ }
+
+ public function __toString() {
+ return "Fail";
+ }
+
+ public function serializeForApiResult() {
+ return $this->ret;
+ }
+}
diff --git a/tests/phpunit/includes/api/ApiTestCase.php b/tests/phpunit/includes/api/ApiTestCase.php
index 8c27b1018a2c..da62bb0a9797 100644
--- a/tests/phpunit/includes/api/ApiTestCase.php
+++ b/tests/phpunit/includes/api/ApiTestCase.php
@@ -116,7 +116,7 @@ abstract class ApiTestCase extends MediaWikiLangTestCase {
// construct result
$results = array(
- $module->getResultData(),
+ $module->getResult()->getResultData( null, array( 'Strip' => 'all' ) ),
$context->getRequest(),
$context->getRequest()->getSessionArray()
);
diff --git a/tests/phpunit/includes/api/MockApi.php b/tests/phpunit/includes/api/MockApi.php
index d94aa2cda562..516da0c8ecc3 100644
--- a/tests/phpunit/includes/api/MockApi.php
+++ b/tests/phpunit/includes/api/MockApi.php
@@ -4,9 +4,6 @@ class MockApi extends ApiBase {
public function execute() {
}
- public function getVersion() {
- }
-
public function __construct() {
}
diff --git a/tests/phpunit/includes/api/MockApiQueryBase.php b/tests/phpunit/includes/api/MockApiQueryBase.php
index 4bede51915dd..f5b50e5a5919 100644
--- a/tests/phpunit/includes/api/MockApiQueryBase.php
+++ b/tests/phpunit/includes/api/MockApiQueryBase.php
@@ -1,11 +1,15 @@
<?php
class MockApiQueryBase extends ApiQueryBase {
+ private $name;
+
public function execute() {
}
- public function getVersion() {
+ public function __construct( $name = 'mock' ) {
+ $this->name = $name;
}
- public function __construct() {
+ public function getModuleName() {
+ return $this->name;
}
}
diff --git a/tests/phpunit/includes/api/format/ApiFormatDbgTest.php b/tests/phpunit/includes/api/format/ApiFormatDbgTest.php
index 1e4ea53ccc4c..3fcfc73fc60d 100644
--- a/tests/phpunit/includes/api/format/ApiFormatDbgTest.php
+++ b/tests/phpunit/includes/api/format/ApiFormatDbgTest.php
@@ -16,8 +16,12 @@ class ApiFormatDbgTest extends ApiFormatTestBase {
return array(
// Basic types
array( array( null ), "array ({$warning}\n 0 => NULL,\n)" ),
- array( array( true ), "array ({$warning}\n 0 => true,\n)" ),
- array( array( false ), "array ({$warning}\n 0 => false,\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)" ),
@@ -29,9 +33,22 @@ class ApiFormatDbgTest extends ApiFormatTestBase {
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( '*' => 'foo' ), "array ({$warning}\n '*' => 'foo',\n)" ),
+ 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
index 2800d2dfb6b8..c0f67f8d82e4 100644
--- a/tests/phpunit/includes/api/format/ApiFormatDumpTest.php
+++ b/tests/phpunit/includes/api/format/ApiFormatDumpTest.php
@@ -24,8 +24,12 @@ class ApiFormatDumpTest extends ApiFormatTestBase {
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 bool(true)\n}\n" ),
- array( array( false ), "array(2) {{$warning}\n [0]=>\n bool(false)\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" ),
@@ -37,9 +41,22 @@ class ApiFormatDumpTest extends ApiFormatTestBase {
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( '*' => 'foo' ), "array(2) {{$warning}\n [\"*\"]=>\n string(3) \"foo\"\n}\n" ),
+ 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 bdf3f139478c..3dfcaf0fd7ec 100644
--- a/tests/phpunit/includes/api/format/ApiFormatJsonTest.php
+++ b/tests/phpunit/includes/api/format/ApiFormatJsonTest.php
@@ -8,34 +8,102 @@ class ApiFormatJsonTest extends ApiFormatTestBase {
protected $printerName = 'json';
+ 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(
- // Basic types
- array( array( null ), '[null]' ),
- array( array( true ), '[true]' ),
- array( array( false ), '[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() ), '[{}]' ),
-
- // Content
- array( array( '*' => 'foo' ), '{"*":"foo"}' ),
-
- // Callbacks
- array( array( 1 ), '/**/myCallback([1])', array( 'callback' => 'myCallback' ) ),
-
- // Cross-domain mangling
- array( array( '< Cross-Domain-Policy >' ), '["\u003C Cross-Domain-Policy \u003E"]' ),
+ 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 1487ad0ddb28..8f81a411e440 100644
--- a/tests/phpunit/includes/api/format/ApiFormatNoneTest.php
+++ b/tests/phpunit/includes/api/format/ApiFormatNoneTest.php
@@ -25,9 +25,19 @@ class ApiFormatNoneTest extends ApiFormatTestBase {
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 469346c8a759..0cb44e921d40 100644
--- a/tests/phpunit/includes/api/format/ApiFormatPhpTest.php
+++ b/tests/phpunit/includes/api/format/ApiFormatPhpTest.php
@@ -8,26 +8,93 @@ class ApiFormatPhpTest extends ApiFormatTestBase {
protected $printerName = 'php';
+ 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(
- // 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( 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";}' ),
+ 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";}}' ),
- // 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;}}' ),
+ // Content
+ array( array( 'content' => 'foo', ApiResult::META_CONTENT => 'content' ),
+ 'a:1:{s:7:"content";s:3:"foo";}' ),
- // Content
- array( array( '*' => 'foo' ), 'a:1:{s:1:"*";s:3:"foo";}' ),
+ // BC Subelements
+ array( array( 'foo' => 'foo', ApiResult::META_BC_SUBELEMENTS => array( 'foo' ) ),
+ 'a:1:{s:3:"foo";s:3:"foo";}' ),
+ ) )
);
}
diff --git a/tests/phpunit/includes/api/format/ApiFormatTxtTest.php b/tests/phpunit/includes/api/format/ApiFormatTxtTest.php
index 06e9204f5b3a..b0a2a9602a11 100644
--- a/tests/phpunit/includes/api/format/ApiFormatTxtTest.php
+++ b/tests/phpunit/includes/api/format/ApiFormatTxtTest.php
@@ -16,8 +16,12 @@ class ApiFormatTxtTest extends ApiFormatTestBase {
return array(
// Basic types
array( array( null ), "Array\n({$warning}\n [0] => \n)\n" ),
- array( array( true ), "Array\n({$warning}\n [0] => 1\n)\n" ),
- array( array( false ), "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" ),
@@ -29,9 +33,22 @@ class ApiFormatTxtTest extends ApiFormatTestBase {
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( '*' => 'foo' ), "Array\n({$warning}\n [*] => foo\n)\n" ),
+ 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 81676e0bf017..07111300aece 100644
--- a/tests/phpunit/includes/api/format/ApiFormatWddxTest.php
+++ b/tests/phpunit/includes/api/format/ApiFormatWddxTest.php
@@ -24,8 +24,12 @@ class ApiFormatWddxTest extends ApiFormatTestBase {
return array(
// Basic types
array( array( null ), "{$p}<var name='0'><null/></var>{$s}" ),
- array( array( true ), "{$p}<var name='0'><boolean value='true'/></var>{$s}" ),
- array( array( false ), "{$p}<var name='0'><boolean value='false'/></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}" ),
@@ -37,9 +41,22 @@ class ApiFormatWddxTest extends ApiFormatTestBase {
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( '*' => 'foo' ), "{$p}<var name='*'><string>foo</string></var>{$s}" ),
+ 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}" ),
);
}
diff --git a/tests/phpunit/includes/api/format/ApiFormatXmlTest.php b/tests/phpunit/includes/api/format/ApiFormatXmlTest.php
index afb47e7134ef..0c31b95770a4 100644
--- a/tests/phpunit/includes/api/format/ApiFormatXmlTest.php
+++ b/tests/phpunit/includes/api/format/ApiFormatXmlTest.php
@@ -9,8 +9,8 @@ class ApiFormatXmlTest extends ApiFormatTestBase {
protected $printerName = 'xml';
- protected function setUp() {
- parent::setUp();
+ 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" />'
@@ -22,29 +22,79 @@ class ApiFormatXmlTest extends ApiFormatTestBase {
}
public static function provideGeneralEncoding() {
- $tests = array(
+ return array(
// Basic types
- array( array( null ), '<?xml version="1.0"?><api><x /></api>' ),
- array( array( true, 'a' => true ), '<?xml version="1.0"?><api a=""><x>1</x></api>' ),
- array( array( false, 'a' => false ), '<?xml version="1.0"?><api><x></x></api>' ),
- array( array( 42, 'a' => 42 ), '<?xml version="1.0"?><api a="42"><x>42</x></api>' ),
- array( array( 42.5, 'a' => 42.5 ), '<?xml version="1.0"?><api a="42.5"><x>42.5</x></api>' ),
- array( array( 1e42, 'a' => 1e42 ), '<?xml version="1.0"?><api a="1.0E+42"><x>1.0E+42</x></api>' ),
- array( array( 'foo', 'a' => 'foo' ), '<?xml version="1.0"?><api a="foo"><x>foo</x></api>' ),
- array( array( 'fóo', 'a' => 'fóo' ), '<?xml version="1.0"?><api a="fóo"><x>fóo</x></api>' ),
+ 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><x /></api>' ),
- array( array( array( 'x' => 1 ) ), '<?xml version="1.0"?><api><x x="1" /></api>' ),
- array( array( array( 2 => 1, '_element' => 'x' ) ), '<?xml version="1.0"?><api><x><x>1</x></x></api>' ),
+ 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( '*' => 'foo' ), '<?xml version="1.0"?><api xml:space="preserve">foo</api>' ),
+ 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" />' ),
+
// includenamespace param
array( array( 'x' => 'foo' ), '<?xml version="1.0"?><api x="foo" xmlns="http://www.mediawiki.org/xml/api/" />',
array( 'includexmlnamespace' => 1 ) ),
@@ -62,40 +112,6 @@ class ApiFormatXmlTest extends ApiFormatTestBase {
'" type="text/xsl" ?><api />',
array( 'xslt' => 'MediaWiki:ApiFormatXmlTest.xsl' ) ),
);
-
- // Add in the needed "_element" for all indexed arrays
- $ret = array();
- foreach ( $tests as $v ) {
- $v[0] += array( '_element' => 'x' );
- $ret[] = $v;
- }
- return $ret;
- }
-
- /**
- * @dataProvider provideXmlFail
- */
- public function testXmlFail( array $data, $expect, array $params = array() ) {
- try {
- echo $this->encodeData( $params, $data ) . "\n";
- $this->fail( "Expected exception not thrown" );
- } catch ( MWException $ex ) {
- $this->assertSame( $expect, $ex->getMessage(), 'Expected exception' );
- }
- }
-
- public static function provideXmlFail() {
- return array(
- // Array without _element
- array( array( 1 ), 'Internal error in ApiFormatXml::recXmlPrint: (api, ...) has integer keys without _element value. Use ApiResult::setIndexedTagName().' ),
- // Content and subelement
- array( array( 1, 's' => array(), '*' => 2, '_element' => 'x' ), 'Internal error in ApiFormatXml::recXmlPrint: (api, ...) has content and subelements' ),
- array( array( 1, 's' => 1, '*' => 2, '_element' => 'x', '_subelements' => array( 's' ) ), 'Internal error in ApiFormatXml::recXmlPrint: (api, ...) has content and subelements' ),
- // These should fail but don't because of a long-standing bug (see T57371#639713)
- //array( array( 1, '*' => 2, '_element' => 'x' ), 'Internal error in ApiFormatXml::recXmlPrint: (api, ...) has content and subelements' ),
- //array( array( 's' => array(), '*' => 2 ), 'Internal error in ApiFormatXml::recXmlPrint: (api, ...) has content and subelements' ),
- //array( array( 's' => 1, '*' => 2, '_subelements' => array( 's' ) ), 'Internal error in ApiFormatXml::recXmlPrint: (api, ...) has content and subelements' ),
- );
}
}