summaryrefslogtreecommitdiff
path: root/www/wiki/tests/phpunit/includes/exception
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/tests/phpunit/includes/exception')
-rw-r--r--www/wiki/tests/phpunit/includes/exception/BadTitleErrorTest.php30
-rw-r--r--www/wiki/tests/phpunit/includes/exception/ErrorPageErrorTest.php52
-rw-r--r--www/wiki/tests/phpunit/includes/exception/HttpErrorTest.php63
-rw-r--r--www/wiki/tests/phpunit/includes/exception/MWExceptionHandlerTest.php74
-rw-r--r--www/wiki/tests/phpunit/includes/exception/MWExceptionTest.php193
-rw-r--r--www/wiki/tests/phpunit/includes/exception/ReadOnlyErrorTest.php16
-rw-r--r--www/wiki/tests/phpunit/includes/exception/ThrottledErrorTest.php31
-rw-r--r--www/wiki/tests/phpunit/includes/exception/UserNotLoggedInTest.php16
8 files changed, 475 insertions, 0 deletions
diff --git a/www/wiki/tests/phpunit/includes/exception/BadTitleErrorTest.php b/www/wiki/tests/phpunit/includes/exception/BadTitleErrorTest.php
new file mode 100644
index 00000000..b706face
--- /dev/null
+++ b/www/wiki/tests/phpunit/includes/exception/BadTitleErrorTest.php
@@ -0,0 +1,30 @@
+<?php
+/**
+ * @covers BadTitleError
+ * @author Addshore
+ */
+class BadTitleErrorTest extends MediaWikiTestCase {
+
+ public function testExceptionSetsStatusCode() {
+ $this->setMwGlobals( 'wgOut', $this->getMockWgOut() );
+ try {
+ throw new BadTitleError();
+ } catch ( BadTitleError $e ) {
+ ob_start();
+ $e->report();
+ $text = ob_get_clean();
+ $this->assertContains( $e->getText(), $text );
+ }
+ }
+
+ private function getMockWgOut() {
+ $mock = $this->getMockBuilder( OutputPage::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+ $mock->expects( $this->once() )
+ ->method( 'setStatusCode' )
+ ->with( 400 );
+ return $mock;
+ }
+
+}
diff --git a/www/wiki/tests/phpunit/includes/exception/ErrorPageErrorTest.php b/www/wiki/tests/phpunit/includes/exception/ErrorPageErrorTest.php
new file mode 100644
index 00000000..49d454e8
--- /dev/null
+++ b/www/wiki/tests/phpunit/includes/exception/ErrorPageErrorTest.php
@@ -0,0 +1,52 @@
+<?php
+
+/**
+ * @covers ErrorPageError
+ * @author Addshore
+ */
+class ErrorPageErrorTest extends MediaWikiTestCase {
+
+ private function getMockMessage() {
+ $mockMessage = $this->getMockBuilder( Message::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+ $mockMessage->expects( $this->once() )
+ ->method( 'inLanguage' )
+ ->will( $this->returnValue( $mockMessage ) );
+ $mockMessage->expects( $this->once() )
+ ->method( 'useDatabase' )
+ ->will( $this->returnValue( $mockMessage ) );
+ return $mockMessage;
+ }
+
+ public function testConstruction() {
+ $mockMessage = $this->getMockMessage();
+ $title = 'Foo';
+ $params = [ 'Baz' ];
+ $e = new ErrorPageError( $title, $mockMessage, $params );
+ $this->assertEquals( $title, $e->title );
+ $this->assertEquals( $mockMessage, $e->msg );
+ $this->assertEquals( $params, $e->params );
+ }
+
+ public function testReport() {
+ $mockMessage = $this->getMockMessage();
+ $title = 'Foo';
+ $params = [ 'Baz' ];
+
+ $mock = $this->getMockBuilder( OutputPage::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+ $mock->expects( $this->once() )
+ ->method( 'showErrorPage' )
+ ->with( $title, $mockMessage, $params );
+ $mock->expects( $this->once() )
+ ->method( 'output' );
+ $this->setMwGlobals( 'wgOut', $mock );
+ $this->setMwGlobals( 'wgCommandLineMode', false );
+
+ $e = new ErrorPageError( $title, $mockMessage, $params );
+ $e->report();
+ }
+
+}
diff --git a/www/wiki/tests/phpunit/includes/exception/HttpErrorTest.php b/www/wiki/tests/phpunit/includes/exception/HttpErrorTest.php
new file mode 100644
index 00000000..90ccd1e5
--- /dev/null
+++ b/www/wiki/tests/phpunit/includes/exception/HttpErrorTest.php
@@ -0,0 +1,63 @@
+<?php
+
+/**
+ * @todo tests for HttpError::report
+ *
+ * @covers HttpError
+ */
+class HttpErrorTest extends MediaWikiTestCase {
+
+ public function testIsLoggable() {
+ $httpError = new HttpError( 500, 'server error!' );
+ $this->assertFalse( $httpError->isLoggable(), 'http error is not loggable' );
+ }
+
+ public function testGetStatusCode() {
+ $httpError = new HttpError( 500, 'server error!' );
+ $this->assertEquals( 500, $httpError->getStatusCode() );
+ }
+
+ /**
+ * @dataProvider getHtmlProvider
+ */
+ public function testGetHtml( array $expected, $content, $header ) {
+ $httpError = new HttpError( 500, $content, $header );
+ $errorHtml = $httpError->getHTML();
+
+ foreach ( $expected as $key => $html ) {
+ $this->assertContains( $html, $errorHtml, $key );
+ }
+ }
+
+ public function getHtmlProvider() {
+ return [
+ [
+ [
+ 'head html' => '<head><title>Server Error 123</title></head>',
+ 'body html' => '<body><h1>Server Error 123</h1>'
+ . '<p>a server error!</p></body>'
+ ],
+ 'a server error!',
+ 'Server Error 123'
+ ],
+ [
+ [
+ 'head html' => '<head><title>loginerror</title></head>',
+ 'body html' => '<body><h1>loginerror</h1>'
+ . '<p>suspicious-userlogout</p></body>'
+ ],
+ new RawMessage( 'suspicious-userlogout' ),
+ new RawMessage( 'loginerror' )
+ ],
+ [
+ [
+ 'head html' => '<html><head><title>Internal Server Error</title></head>',
+ 'body html' => '<body><h1>Internal Server Error</h1>'
+ . '<p>a server error!</p></body></html>'
+ ],
+ 'a server error!',
+ null
+ ]
+ ];
+ }
+}
diff --git a/www/wiki/tests/phpunit/includes/exception/MWExceptionHandlerTest.php b/www/wiki/tests/phpunit/includes/exception/MWExceptionHandlerTest.php
new file mode 100644
index 00000000..66060656
--- /dev/null
+++ b/www/wiki/tests/phpunit/includes/exception/MWExceptionHandlerTest.php
@@ -0,0 +1,74 @@
+<?php
+/**
+ * @author Antoine Musso
+ * @copyright Copyright © 2013, Antoine Musso
+ * @copyright Copyright © 2013, Wikimedia Foundation Inc.
+ * @file
+ */
+
+class MWExceptionHandlerTest extends MediaWikiTestCase {
+
+ /**
+ * @covers MWExceptionHandler::getRedactedTrace
+ */
+ public function testGetRedactedTrace() {
+ $refvar = 'value';
+ try {
+ $array = [ 'a', 'b' ];
+ $object = new stdClass();
+ self::helperThrowAnException( $array, $object, $refvar );
+ } catch ( Exception $e ) {
+ }
+
+ # Make sure our stack trace contains an array and an object passed to
+ # some function in the stacktrace. Else, we can not assert the trace
+ # redaction achieved its job.
+ $trace = $e->getTrace();
+ $hasObject = false;
+ $hasArray = false;
+ foreach ( $trace as $frame ) {
+ if ( !isset( $frame['args'] ) ) {
+ continue;
+ }
+ foreach ( $frame['args'] as $arg ) {
+ $hasObject = $hasObject || is_object( $arg );
+ $hasArray = $hasArray || is_array( $arg );
+ }
+
+ if ( $hasObject && $hasArray ) {
+ break;
+ }
+ }
+ $this->assertTrue( $hasObject,
+ "The stacktrace must have a function having an object has parameter" );
+ $this->assertTrue( $hasArray,
+ "The stacktrace must have a function having an array has parameter" );
+
+ # Now we redact the trace.. and make sure no function arguments are
+ # arrays or objects.
+ $redacted = MWExceptionHandler::getRedactedTrace( $e );
+
+ foreach ( $redacted as $frame ) {
+ if ( !isset( $frame['args'] ) ) {
+ continue;
+ }
+ foreach ( $frame['args'] as $arg ) {
+ $this->assertNotInternalType( 'array', $arg );
+ $this->assertNotInternalType( 'object', $arg );
+ }
+ }
+
+ $this->assertEquals( 'value', $refvar, 'Ensuring reference variable wasn\'t changed' );
+ }
+
+ /**
+ * Helper function for testExpandArgumentsInCall
+ *
+ * Pass it an object and an array, and something by reference :-)
+ *
+ * @throws Exception
+ */
+ protected static function helperThrowAnException( $a, $b, &$c ) {
+ throw new Exception();
+ }
+}
diff --git a/www/wiki/tests/phpunit/includes/exception/MWExceptionTest.php b/www/wiki/tests/phpunit/includes/exception/MWExceptionTest.php
new file mode 100644
index 00000000..b1605549
--- /dev/null
+++ b/www/wiki/tests/phpunit/includes/exception/MWExceptionTest.php
@@ -0,0 +1,193 @@
+<?php
+/**
+ * @author Antoine Musso
+ * @copyright Copyright © 2013, Antoine Musso
+ * @copyright Copyright © 2013, Wikimedia Foundation Inc.
+ * @file
+ */
+
+class MWExceptionTest extends MediaWikiTestCase {
+
+ /**
+ * @expectedException MWException
+ * @covers MWException
+ */
+ public function testMwexceptionThrowing() {
+ throw new MWException();
+ }
+
+ /**
+ * @dataProvider provideTextUseOutputPage
+ * @covers MWException::useOutputPage
+ */
+ public function testUseOutputPage( $expected, $langObj, $wgFullyInitialised, $wgOut ) {
+ $this->setMwGlobals( [
+ 'wgLang' => $langObj,
+ 'wgFullyInitialised' => $wgFullyInitialised,
+ 'wgOut' => $wgOut,
+ ] );
+
+ $e = new MWException();
+ $this->assertEquals( $expected, $e->useOutputPage() );
+ }
+
+ public function provideTextUseOutputPage() {
+ return [
+ // expected, langObj, wgFullyInitialised, wgOut
+ [ false, null, null, null ],
+ [ false, $this->getMockLanguage(), null, null ],
+ [ false, $this->getMockLanguage(), true, null ],
+ [ false, null, true, null ],
+ [ false, null, null, true ],
+ [ true, $this->getMockLanguage(), true, true ],
+ ];
+ }
+
+ private function getMockLanguage() {
+ return $this->getMockBuilder( Language::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
+
+ /**
+ * @dataProvider provideUseMessageCache
+ * @covers MWException::useMessageCache
+ */
+ public function testUseMessageCache( $expected, $langObj ) {
+ $this->setMwGlobals( [
+ 'wgLang' => $langObj,
+ ] );
+ $e = new MWException();
+ $this->assertEquals( $expected, $e->useMessageCache() );
+ }
+
+ public function provideUseMessageCache() {
+ return [
+ [ false, null ],
+ [ true, $this->getMockLanguage() ],
+ ];
+ }
+
+ /**
+ * @covers MWException::isLoggable
+ */
+ public function testIsLogable() {
+ $e = new MWException();
+ $this->assertTrue( $e->isLoggable() );
+ }
+
+ /**
+ * @dataProvider provideIsCommandLine
+ * @covers MWException::isCommandLine
+ */
+ public function testisCommandLine( $expected, $wgCommandLineMode ) {
+ $this->setMwGlobals( [
+ 'wgCommandLineMode' => $wgCommandLineMode,
+ ] );
+ $e = new MWException();
+ $this->assertEquals( $expected, $e->isCommandLine() );
+ }
+
+ public static function provideIsCommandLine() {
+ return [
+ [ false, null ],
+ [ true, true ],
+ ];
+ }
+
+ /**
+ * Verify the exception classes are JSON serializabe.
+ *
+ * @covers MWExceptionHandler::jsonSerializeException
+ * @dataProvider provideExceptionClasses
+ */
+ public function testJsonSerializeExceptions( $exception_class ) {
+ $json = MWExceptionHandler::jsonSerializeException(
+ new $exception_class()
+ );
+ $this->assertNotEquals( false, $json,
+ "The $exception_class exception should be JSON serializable, got false." );
+ }
+
+ public static function provideExceptionClasses() {
+ return [
+ [ Exception::class ],
+ [ MWException::class ],
+ ];
+ }
+
+ /**
+ * Lame JSON schema validation.
+ *
+ * @covers MWExceptionHandler::jsonSerializeException
+ *
+ * @param string $expectedKeyType Type expected as returned by gettype()
+ * @param string $exClass An exception class (ie: Exception, MWException)
+ * @param string $key Name of the key to validate in the serialized JSON
+ * @dataProvider provideJsonSerializedKeys
+ */
+ public function testJsonserializeexceptionKeys( $expectedKeyType, $exClass, $key ) {
+ # Make sure we log a backtrace:
+ $this->setMwGlobals( [ 'wgLogExceptionBacktrace' => true ] );
+
+ $json = json_decode(
+ MWExceptionHandler::jsonSerializeException( new $exClass() )
+ );
+ $this->assertObjectHasAttribute( $key, $json,
+ "JSON serialized exception is missing key '$key'"
+ );
+ $this->assertInternalType( $expectedKeyType, $json->$key,
+ "JSON serialized key '$key' has type " . gettype( $json->$key )
+ . " (expected: $expectedKeyType)."
+ );
+ }
+
+ /**
+ * Returns test cases: exception class, key name, gettype()
+ */
+ public static function provideJsonSerializedKeys() {
+ $testCases = [];
+ foreach ( [ Exception::class, MWException::class ] as $exClass ) {
+ $exTests = [
+ [ 'string', $exClass, 'id' ],
+ [ 'string', $exClass, 'file' ],
+ [ 'integer', $exClass, 'line' ],
+ [ 'string', $exClass, 'message' ],
+ [ 'null', $exClass, 'url' ],
+ # Backtrace only enabled with wgLogExceptionBacktrace = true
+ [ 'array', $exClass, 'backtrace' ],
+ ];
+ $testCases = array_merge( $testCases, $exTests );
+ }
+ return $testCases;
+ }
+
+ /**
+ * Given wgLogExceptionBacktrace is true
+ * then serialized exception SHOULD have a backtrace
+ *
+ * @covers MWExceptionHandler::jsonSerializeException
+ */
+ public function testJsonserializeexceptionBacktracingEnabled() {
+ $this->setMwGlobals( [ 'wgLogExceptionBacktrace' => true ] );
+ $json = json_decode(
+ MWExceptionHandler::jsonSerializeException( new Exception() )
+ );
+ $this->assertObjectHasAttribute( 'backtrace', $json );
+ }
+
+ /**
+ * Given wgLogExceptionBacktrace is false
+ * then serialized exception SHOULD NOT have a backtrace
+ *
+ * @covers MWExceptionHandler::jsonSerializeException
+ */
+ public function testJsonserializeexceptionBacktracingDisabled() {
+ $this->setMwGlobals( [ 'wgLogExceptionBacktrace' => false ] );
+ $json = json_decode(
+ MWExceptionHandler::jsonSerializeException( new Exception() )
+ );
+ $this->assertObjectNotHasAttribute( 'backtrace', $json );
+ }
+
+}
diff --git a/www/wiki/tests/phpunit/includes/exception/ReadOnlyErrorTest.php b/www/wiki/tests/phpunit/includes/exception/ReadOnlyErrorTest.php
new file mode 100644
index 00000000..ee5becff
--- /dev/null
+++ b/www/wiki/tests/phpunit/includes/exception/ReadOnlyErrorTest.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * @covers ReadOnlyError
+ * @author Addshore
+ */
+class ReadOnlyErrorTest extends MediaWikiTestCase {
+
+ public function testConstruction() {
+ $e = new ReadOnlyError();
+ $this->assertEquals( 'readonly', $e->title );
+ $this->assertEquals( 'readonlytext', $e->msg );
+ $this->assertEquals( wfReadOnlyReason() ?: [], $e->params );
+ }
+
+}
diff --git a/www/wiki/tests/phpunit/includes/exception/ThrottledErrorTest.php b/www/wiki/tests/phpunit/includes/exception/ThrottledErrorTest.php
new file mode 100644
index 00000000..5214b6d4
--- /dev/null
+++ b/www/wiki/tests/phpunit/includes/exception/ThrottledErrorTest.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * @covers ThrottledError
+ * @author Addshore
+ */
+class ThrottledErrorTest extends MediaWikiTestCase {
+
+ public function testExceptionSetsStatusCode() {
+ $this->setMwGlobals( 'wgOut', $this->getMockWgOut() );
+ try {
+ throw new ThrottledError();
+ } catch ( ThrottledError $e ) {
+ ob_start();
+ $e->report();
+ $text = ob_get_clean();
+ $this->assertContains( $e->getText(), $text );
+ }
+ }
+
+ private function getMockWgOut() {
+ $mock = $this->getMockBuilder( OutputPage::class )
+ ->disableOriginalConstructor()
+ ->getMock();
+ $mock->expects( $this->once() )
+ ->method( 'setStatusCode' )
+ ->with( 429 );
+ return $mock;
+ }
+
+}
diff --git a/www/wiki/tests/phpunit/includes/exception/UserNotLoggedInTest.php b/www/wiki/tests/phpunit/includes/exception/UserNotLoggedInTest.php
new file mode 100644
index 00000000..55ec45a0
--- /dev/null
+++ b/www/wiki/tests/phpunit/includes/exception/UserNotLoggedInTest.php
@@ -0,0 +1,16 @@
+<?php
+
+/**
+ * @covers UserNotLoggedIn
+ * @author Addshore
+ */
+class UserNotLoggedInTest extends MediaWikiTestCase {
+
+ public function testConstruction() {
+ $e = new UserNotLoggedIn();
+ $this->assertEquals( 'exception-nologin', $e->title );
+ $this->assertEquals( 'exception-nologin-text', $e->msg );
+ $this->assertEquals( [], $e->params );
+ }
+
+}