2013-10-23 15:36:40 +00:00
|
|
|
|
<?php
|
|
|
|
|
|
|
2017-04-19 19:37:35 +00:00
|
|
|
|
use Wikimedia\TestingAccessWrapper;
|
|
|
|
|
|
|
2013-10-23 15:36:40 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @group API
|
|
|
|
|
|
* @group Database
|
|
|
|
|
|
* @group medium
|
|
|
|
|
|
*/
|
|
|
|
|
|
class ApiBaseTest extends ApiTestCase {
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @covers ApiBase::requireOnlyOneParameter
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function testRequireOnlyOneParameterDefault() {
|
|
|
|
|
|
$mock = new MockApi();
|
|
|
|
|
|
$mock->requireOnlyOneParameter(
|
2016-02-17 09:09:32 +00:00
|
|
|
|
[ "filename" => "foo.txt", "enablechunks" => false ],
|
2013-10-23 15:36:40 +00:00
|
|
|
|
"filename", "enablechunks"
|
|
|
|
|
|
);
|
|
|
|
|
|
$this->assertTrue( true );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2016-10-19 16:54:25 +00:00
|
|
|
|
* @expectedException ApiUsageException
|
2013-10-23 15:36:40 +00:00
|
|
|
|
* @covers ApiBase::requireOnlyOneParameter
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function testRequireOnlyOneParameterZero() {
|
|
|
|
|
|
$mock = new MockApi();
|
|
|
|
|
|
$mock->requireOnlyOneParameter(
|
2016-02-17 09:09:32 +00:00
|
|
|
|
[ "filename" => "foo.txt", "enablechunks" => 0 ],
|
2013-10-23 15:36:40 +00:00
|
|
|
|
"filename", "enablechunks"
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2016-10-19 16:54:25 +00:00
|
|
|
|
* @expectedException ApiUsageException
|
2013-10-23 15:36:40 +00:00
|
|
|
|
* @covers ApiBase::requireOnlyOneParameter
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function testRequireOnlyOneParameterTrue() {
|
|
|
|
|
|
$mock = new MockApi();
|
|
|
|
|
|
$mock->requireOnlyOneParameter(
|
2016-02-17 09:09:32 +00:00
|
|
|
|
[ "filename" => "foo.txt", "enablechunks" => true ],
|
2013-10-23 15:36:40 +00:00
|
|
|
|
"filename", "enablechunks"
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-08-16 20:36:27 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @dataProvider provideGetParameterFromSettings
|
|
|
|
|
|
* @param string|null $input
|
|
|
|
|
|
* @param array $paramSettings
|
|
|
|
|
|
* @param mixed $expected
|
|
|
|
|
|
* @param string[] $warnings
|
2017-12-24 23:44:36 +00:00
|
|
|
|
* @covers ApiBase::getParameterFromSettings
|
2016-08-16 20:36:27 +00:00
|
|
|
|
*/
|
|
|
|
|
|
public function testGetParameterFromSettings( $input, $paramSettings, $expected, $warnings ) {
|
|
|
|
|
|
$mock = new MockApi();
|
|
|
|
|
|
$wrapper = TestingAccessWrapper::newFromObject( $mock );
|
|
|
|
|
|
|
|
|
|
|
|
$context = new DerivativeContext( $mock );
|
|
|
|
|
|
$context->setRequest( new FauxRequest( $input !== null ? [ 'foo' => $input ] : [] ) );
|
|
|
|
|
|
$wrapper->mMainModule = new ApiMain( $context );
|
|
|
|
|
|
|
2016-10-19 16:54:25 +00:00
|
|
|
|
if ( $expected instanceof ApiUsageException ) {
|
2016-08-16 20:36:27 +00:00
|
|
|
|
try {
|
|
|
|
|
|
$wrapper->getParameterFromSettings( 'foo', $paramSettings, true );
|
2016-10-19 16:54:25 +00:00
|
|
|
|
} catch ( ApiUsageException $ex ) {
|
2016-08-16 20:36:27 +00:00
|
|
|
|
$this->assertEquals( $expected, $ex );
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$result = $wrapper->getParameterFromSettings( 'foo', $paramSettings, true );
|
|
|
|
|
|
$this->assertSame( $expected, $result );
|
|
|
|
|
|
$this->assertSame( $warnings, $mock->warnings );
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static function provideGetParameterFromSettings() {
|
2016-08-24 18:07:43 +00:00
|
|
|
|
$warnings = [
|
2016-10-19 16:54:25 +00:00
|
|
|
|
[ 'apiwarn-badutf8', 'foo' ],
|
2016-08-24 18:07:43 +00:00
|
|
|
|
];
|
|
|
|
|
|
|
2016-08-16 20:36:27 +00:00
|
|
|
|
$c0 = '';
|
|
|
|
|
|
$enc = '';
|
|
|
|
|
|
for ( $i = 0; $i < 32; $i++ ) {
|
|
|
|
|
|
$c0 .= chr( $i );
|
|
|
|
|
|
$enc .= ( $i === 9 || $i === 10 || $i === 13 )
|
|
|
|
|
|
? chr( $i )
|
|
|
|
|
|
: '<27>';
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return [
|
|
|
|
|
|
'Basic param' => [ 'bar', null, 'bar', [] ],
|
2016-08-24 18:07:43 +00:00
|
|
|
|
'Basic param, C0 controls' => [ $c0, null, $enc, $warnings ],
|
2016-08-16 20:36:27 +00:00
|
|
|
|
'String param' => [ 'bar', '', 'bar', [] ],
|
|
|
|
|
|
'String param, defaulted' => [ null, '', '', [] ],
|
|
|
|
|
|
'String param, empty' => [ '', 'default', '', [] ],
|
|
|
|
|
|
'String param, required, empty' => [
|
|
|
|
|
|
'',
|
|
|
|
|
|
[ ApiBase::PARAM_DFLT => 'default', ApiBase::PARAM_REQUIRED => true ],
|
2016-10-19 16:54:25 +00:00
|
|
|
|
ApiUsageException::newWithMessage( null, [ 'apierror-missingparam', 'foo' ] ),
|
2016-08-16 20:36:27 +00:00
|
|
|
|
[]
|
|
|
|
|
|
],
|
|
|
|
|
|
'Multi-valued parameter' => [
|
|
|
|
|
|
'a|b|c',
|
|
|
|
|
|
[ ApiBase::PARAM_ISMULTI => true ],
|
|
|
|
|
|
[ 'a', 'b', 'c' ],
|
|
|
|
|
|
[]
|
|
|
|
|
|
],
|
|
|
|
|
|
'Multi-valued parameter, alternative separator' => [
|
|
|
|
|
|
"\x1fa|b\x1fc|d",
|
|
|
|
|
|
[ ApiBase::PARAM_ISMULTI => true ],
|
|
|
|
|
|
[ 'a|b', 'c|d' ],
|
|
|
|
|
|
[]
|
|
|
|
|
|
],
|
|
|
|
|
|
'Multi-valued parameter, other C0 controls' => [
|
|
|
|
|
|
$c0,
|
|
|
|
|
|
[ ApiBase::PARAM_ISMULTI => true ],
|
|
|
|
|
|
[ $enc ],
|
2016-08-24 18:07:43 +00:00
|
|
|
|
$warnings
|
2016-08-16 20:36:27 +00:00
|
|
|
|
],
|
|
|
|
|
|
'Multi-valued parameter, other C0 controls (2)' => [
|
|
|
|
|
|
"\x1f" . $c0,
|
|
|
|
|
|
[ ApiBase::PARAM_ISMULTI => true ],
|
|
|
|
|
|
[ substr( $enc, 0, -3 ), '' ],
|
2016-08-24 18:07:43 +00:00
|
|
|
|
$warnings
|
2016-08-16 20:36:27 +00:00
|
|
|
|
],
|
|
|
|
|
|
];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-12-24 23:44:36 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @covers ApiBase::errorArrayToStatus
|
|
|
|
|
|
*/
|
2016-10-19 16:54:25 +00:00
|
|
|
|
public function testErrorArrayToStatus() {
|
|
|
|
|
|
$mock = new MockApi();
|
|
|
|
|
|
|
|
|
|
|
|
// Sanity check empty array
|
|
|
|
|
|
$expect = Status::newGood();
|
|
|
|
|
|
$this->assertEquals( $expect, $mock->errorArrayToStatus( [] ) );
|
|
|
|
|
|
|
|
|
|
|
|
// No blocked $user, so no special block handling
|
|
|
|
|
|
$expect = Status::newGood();
|
|
|
|
|
|
$expect->fatal( 'blockedtext' );
|
|
|
|
|
|
$expect->fatal( 'autoblockedtext' );
|
2016-12-01 16:51:03 +00:00
|
|
|
|
$expect->fatal( 'systemblockedtext' );
|
2016-10-19 16:54:25 +00:00
|
|
|
|
$expect->fatal( 'mainpage' );
|
|
|
|
|
|
$expect->fatal( 'parentheses', 'foobar' );
|
|
|
|
|
|
$this->assertEquals( $expect, $mock->errorArrayToStatus( [
|
|
|
|
|
|
[ 'blockedtext' ],
|
|
|
|
|
|
[ 'autoblockedtext' ],
|
2016-12-01 16:51:03 +00:00
|
|
|
|
[ 'systemblockedtext' ],
|
2016-10-19 16:54:25 +00:00
|
|
|
|
'mainpage',
|
|
|
|
|
|
[ 'parentheses', 'foobar' ],
|
|
|
|
|
|
] ) );
|
|
|
|
|
|
|
|
|
|
|
|
// Has a blocked $user, so special block handling
|
|
|
|
|
|
$user = $this->getMutableTestUser()->getUser();
|
|
|
|
|
|
$block = new \Block( [
|
|
|
|
|
|
'address' => $user->getName(),
|
|
|
|
|
|
'user' => $user->getID(),
|
|
|
|
|
|
'reason' => __METHOD__,
|
|
|
|
|
|
'expiry' => time() + 100500,
|
|
|
|
|
|
] );
|
|
|
|
|
|
$block->insert();
|
|
|
|
|
|
$blockinfo = [ 'blockinfo' => ApiQueryUserInfo::getBlockInfo( $block ) ];
|
|
|
|
|
|
|
|
|
|
|
|
$expect = Status::newGood();
|
|
|
|
|
|
$expect->fatal( ApiMessage::create( 'apierror-blocked', 'blocked', $blockinfo ) );
|
|
|
|
|
|
$expect->fatal( ApiMessage::create( 'apierror-autoblocked', 'autoblocked', $blockinfo ) );
|
2016-12-01 16:51:03 +00:00
|
|
|
|
$expect->fatal( ApiMessage::create( 'apierror-systemblocked', 'blocked', $blockinfo ) );
|
2016-10-19 16:54:25 +00:00
|
|
|
|
$expect->fatal( 'mainpage' );
|
|
|
|
|
|
$expect->fatal( 'parentheses', 'foobar' );
|
|
|
|
|
|
$this->assertEquals( $expect, $mock->errorArrayToStatus( [
|
|
|
|
|
|
[ 'blockedtext' ],
|
|
|
|
|
|
[ 'autoblockedtext' ],
|
2016-12-01 16:51:03 +00:00
|
|
|
|
[ 'systemblockedtext' ],
|
2016-10-19 16:54:25 +00:00
|
|
|
|
'mainpage',
|
|
|
|
|
|
[ 'parentheses', 'foobar' ],
|
|
|
|
|
|
], $user ) );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-06-12 16:54:24 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @covers ApiBase::dieStatus
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function testDieStatus() {
|
|
|
|
|
|
$mock = new MockApi();
|
|
|
|
|
|
|
|
|
|
|
|
$status = StatusValue::newGood();
|
|
|
|
|
|
$status->error( 'foo' );
|
|
|
|
|
|
$status->warning( 'bar' );
|
|
|
|
|
|
try {
|
|
|
|
|
|
$mock->dieStatus( $status );
|
|
|
|
|
|
$this->fail( 'Expected exception not thrown' );
|
|
|
|
|
|
} catch ( ApiUsageException $ex ) {
|
|
|
|
|
|
$this->assertTrue( ApiTestCase::apiExceptionHasCode( $ex, 'foo' ), 'Exception has "foo"' );
|
|
|
|
|
|
$this->assertFalse( ApiTestCase::apiExceptionHasCode( $ex, 'bar' ), 'Exception has "bar"' );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$status = StatusValue::newGood();
|
|
|
|
|
|
$status->warning( 'foo' );
|
|
|
|
|
|
$status->warning( 'bar' );
|
|
|
|
|
|
try {
|
|
|
|
|
|
$mock->dieStatus( $status );
|
|
|
|
|
|
$this->fail( 'Expected exception not thrown' );
|
|
|
|
|
|
} catch ( ApiUsageException $ex ) {
|
|
|
|
|
|
$this->assertTrue( ApiTestCase::apiExceptionHasCode( $ex, 'foo' ), 'Exception has "foo"' );
|
|
|
|
|
|
$this->assertTrue( ApiTestCase::apiExceptionHasCode( $ex, 'bar' ), 'Exception has "bar"' );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$status = StatusValue::newGood();
|
|
|
|
|
|
$status->setOk( false );
|
|
|
|
|
|
try {
|
|
|
|
|
|
$mock->dieStatus( $status );
|
|
|
|
|
|
$this->fail( 'Expected exception not thrown' );
|
|
|
|
|
|
} catch ( ApiUsageException $ex ) {
|
|
|
|
|
|
$this->assertTrue( ApiTestCase::apiExceptionHasCode( $ex, 'unknownerror-nocode' ),
|
|
|
|
|
|
'Exception has "unknownerror-nocode"' );
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2013-10-23 15:36:40 +00:00
|
|
|
|
}
|