$context->setLanguage( 'en' );
$context->setConfig( new MultiConfig( [
new HashConfig( [
- 'ShowHostnames' => true, 'ShowSQLErrors' => false,
- 'ShowExceptionDetails' => true, 'ShowDBErrorBacktrace' => true,
+ 'ShowHostnames' => true, 'ShowExceptionDetails' => true,
] ),
$context->getConfig()
] ) );
MWExceptionHandler::getRedactedTraceAsString( $dbex )
)->inLanguage( 'en' )->useDatabase( false )->text();
- Wikimedia\suppressWarnings();
- $usageEx = new UsageException( 'Usage exception!', 'ue', 0, [ 'foo' => 'bar' ] );
- Wikimedia\restoreWarnings();
+ // The specific exception doesn't matter, as long as it's namespaced.
+ $nsex = new MediaWiki\ShellDisabledError();
+ $nstrace = wfMessage( 'api-exception-trace',
+ get_class( $nsex ),
+ $nsex->getFile(),
+ $nsex->getLine(),
+ MWExceptionHandler::getRedactedTraceAsString( $nsex )
+ )->inLanguage( 'en' )->useDatabase( false )->text();
$apiEx1 = new ApiUsageException( null,
StatusValue::newFatal( new ApiRawMessage( 'An error', 'sv-error1' ) ) );
$apiEx1->getStatusValue()->warning( new ApiRawMessage( 'Another warning', 'sv-warn2' ) );
$apiEx1->getStatusValue()->fatal( new ApiRawMessage( 'Another error', 'sv-error2' ) );
+ $badMsg = $this->getMockBuilder( ApiRawMessage::class )
+ ->setConstructorArgs( [ 'An error', 'ignored' ] )
+ ->setMethods( [ 'getApiCode' ] )
+ ->getMock();
+ $badMsg->method( 'getApiCode' )->willReturn( "bad\nvalue" );
+ $apiEx2 = new ApiUsageException( null, StatusValue::newFatal( $badMsg ) );
+
return [
[
$ex,
[ 'code' => 'existing-error', 'text' => 'existing error', 'module' => 'main' ],
[
'code' => 'internal_api_error_DBQueryError',
- 'text' => "[$reqId] Database query error.",
+ 'text' => "[$reqId] Exception caught: A database query error has occurred. " .
+ "This may indicate a bug in the software.",
]
],
'trace' => $dbtrace,
]
],
[
- $usageEx,
- [ 'existing-error', 'ue' ],
+ $nsex,
+ [ 'existing-error', 'internal_api_error_MediaWiki\ShellDisabledError' ],
[
'warnings' => [
[ 'code' => 'existing-warning', 'text' => 'existing warning', 'module' => 'main' ],
],
'errors' => [
[ 'code' => 'existing-error', 'text' => 'existing error', 'module' => 'main' ],
- [ 'code' => 'ue', 'text' => "Usage exception!", 'data' => [ 'foo' => 'bar' ] ]
+ [
+ 'code' => 'internal_api_error_MediaWiki\ShellDisabledError',
+ 'text' => "[$reqId] Exception caught: " . $nsex->getMessage(),
+ ]
],
- 'docref' => "See $doclink for API usage. Subscribe to the mediawiki-api-announce mailing " .
- "list at <https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce> " .
- "for notice of API deprecations and breaking changes.",
+ 'trace' => $nstrace,
'servedby' => wfHostname(),
]
],
'servedby' => wfHostname(),
]
],
+ [
+ $apiEx2,
+ [ 'existing-error', '<invalid-code>' ],
+ [
+ 'warnings' => [
+ [ 'code' => 'existing-warning', 'text' => 'existing warning', 'module' => 'main' ],
+ ],
+ 'errors' => [
+ [ 'code' => 'existing-error', 'text' => 'existing error', 'module' => 'main' ],
+ [ 'code' => "bad\nvalue", 'text' => 'An error' ],
+ ],
+ 'docref' => "See $doclink for API usage. Subscribe to the mediawiki-api-announce mailing " .
+ "list at <https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce> " .
+ "for notice of API deprecations and breaking changes.",
+ 'servedby' => wfHostname(),
+ ]
+ ]
];
}
+
+ public function testPrinterParameterValidationError() {
+ $api = $this->getNonInternalApiMain( [
+ 'action' => 'query', 'meta' => 'siteinfo', 'format' => 'json', 'formatversion' => 'bogus',
+ ] );
+
+ ob_start();
+ $api->execute();
+ $txt = ob_get_clean();
+
+ // Test that the actual output is valid JSON, not just the format of the ApiResult.
+ $data = FormatJson::decode( $txt, true );
+ $this->assertInternalType( 'array', $data );
+ $this->assertArrayHasKey( 'error', $data );
+ $this->assertArrayHasKey( 'code', $data['error'] );
+ $this->assertSame( 'unknown_formatversion', $data['error']['code'] );
+ }
}