123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- <?php
- require_once __DIR__ . "/../../../maintenance/fetchText.php";
- /**
- * Mock for the input/output of FetchText
- *
- * FetchText internally tries to access stdin and stdout. We mock those aspects
- * for testing.
- */
- class SemiMockedFetchText extends FetchText {
- /**
- * @var string|null Text to pass as stdin
- */
- private $mockStdinText = null;
- /**
- * @var bool Whether or not a text for stdin has been provided
- */
- private $mockSetUp = false;
- /**
- * @var array Invocation counters for the mocked aspects
- */
- private $mockInvocations = [ 'getStdin' => 0 ];
- /**
- * Data for the fake stdin
- *
- * @param string $stdin The string to be used instead of stdin
- */
- function mockStdin( $stdin ) {
- $this->mockStdinText = $stdin;
- $this->mockSetUp = true;
- }
- /**
- * Gets invocation counters for mocked methods.
- *
- * @return array An array, whose keys are function names. The corresponding values
- * denote the number of times the function has been invoked.
- */
- function mockGetInvocations() {
- return $this->mockInvocations;
- }
- // -----------------------------------------------------------------
- // Mocked functions from FetchText follow.
- function getStdin( $len = null ) {
- $this->mockInvocations['getStdin']++;
- if ( $len !== null ) {
- throw new PHPUnit_Framework_ExpectationFailedException(
- "Tried to get stdin with non null parameter" );
- }
- if ( !$this->mockSetUp ) {
- throw new PHPUnit_Framework_ExpectationFailedException(
- "Tried to get stdin before setting up rerouting" );
- }
- return fopen( 'data://text/plain,' . $this->mockStdinText, 'r' );
- }
- }
- /**
- * TestCase for FetchText
- *
- * @group Database
- * @group Dump
- * @covers FetchText
- */
- class FetchTextTest extends MediaWikiTestCase {
- // We add 5 Revisions for this test. Their corresponding text id's
- // are stored in the following 5 variables.
- private $textId1;
- private $textId2;
- private $textId3;
- private $textId4;
- private $textId5;
- /**
- * @var Exception|null As the current MediaWikiTestCase::run is not
- * robust enough to recover from thrown exceptions directly, we cannot
- * throw frow within addDBData, although it would be appropriate. Hence,
- * we catch the exception and store it until we are in setUp and may
- * finally rethrow the exception without crashing the test suite.
- */
- private $exceptionFromAddDBData;
- /**
- * @var FetchText The (mocked) FetchText that is to test
- */
- private $fetchText;
- /**
- * Adds a revision to a page, while returning the resuting text's id
- *
- * @param WikiPage $page The page to add the revision to
- * @param string $text The revisions text
- * @param string $summary The revisions summare
- * @return int
- * @throws MWException
- */
- private function addRevision( $page, $text, $summary ) {
- $status = $page->doEditContent(
- ContentHandler::makeContent( $text, $page->getTitle() ),
- $summary
- );
- if ( $status->isGood() ) {
- $value = $status->getValue();
- $revision = $value['revision'];
- $id = $revision->getTextId();
- if ( $id > 0 ) {
- return $id;
- }
- }
- throw new MWException( "Could not determine text id" );
- }
- function addDBData() {
- $this->tablesUsed[] = 'page';
- $this->tablesUsed[] = 'revision';
- $this->tablesUsed[] = 'text';
- $wikitextNamespace = $this->getDefaultWikitextNS();
- try {
- $title = Title::newFromText( 'FetchTextTestPage1', $wikitextNamespace );
- $page = WikiPage::factory( $title );
- $this->textId1 = $this->addRevision(
- $page,
- "FetchTextTestPage1Text1",
- "FetchTextTestPage1Summary1"
- );
- $title = Title::newFromText( 'FetchTextTestPage2', $wikitextNamespace );
- $page = WikiPage::factory( $title );
- $this->textId2 = $this->addRevision(
- $page,
- "FetchTextTestPage2Text1",
- "FetchTextTestPage2Summary1"
- );
- $this->textId3 = $this->addRevision(
- $page,
- "FetchTextTestPage2Text2",
- "FetchTextTestPage2Summary2"
- );
- $this->textId4 = $this->addRevision(
- $page,
- "FetchTextTestPage2Text3",
- "FetchTextTestPage2Summary3"
- );
- $this->textId5 = $this->addRevision(
- $page,
- "FetchTextTestPage2Text4 some additional Text ",
- "FetchTextTestPage2Summary4 extra "
- );
- } catch ( Exception $e ) {
- // We'd love to pass $e directly. However, ... see
- // documentation of exceptionFromAddDBData
- $this->exceptionFromAddDBData = $e;
- }
- }
- protected function setUp() {
- parent::setUp();
- // Check if any Exception is stored for rethrowing from addDBData
- if ( $this->exceptionFromAddDBData !== null ) {
- throw $this->exceptionFromAddDBData;
- }
- $this->fetchText = new SemiMockedFetchText();
- }
- /**
- * Helper to relate FetchText's input and output
- * @param string $input
- * @param string $expectedOutput
- */
- private function assertFilter( $input, $expectedOutput ) {
- $this->fetchText->mockStdin( $input );
- $this->fetchText->execute();
- $invocations = $this->fetchText->mockGetInvocations();
- $this->assertEquals( 1, $invocations['getStdin'],
- "getStdin invocation counter" );
- $this->expectOutputString( $expectedOutput );
- }
- // Instead of the following functions, a data provider would be great.
- // However, as data providers are evaluated /before/ addDBData, a data
- // provider would not know the required ids.
- function testExistingSimple() {
- $this->assertFilter( $this->textId2,
- $this->textId2 . "\n23\nFetchTextTestPage2Text1" );
- }
- function testExistingSimpleWithNewline() {
- $this->assertFilter( $this->textId2 . "\n",
- $this->textId2 . "\n23\nFetchTextTestPage2Text1" );
- }
- function testExistingSeveral() {
- $this->assertFilter( "$this->textId1\n$this->textId5\n"
- . "$this->textId3\n$this->textId3",
- implode( "", [
- $this->textId1 . "\n23\nFetchTextTestPage1Text1",
- $this->textId5 . "\n44\nFetchTextTestPage2Text4 "
- . "some additional Text",
- $this->textId3 . "\n23\nFetchTextTestPage2Text2",
- $this->textId3 . "\n23\nFetchTextTestPage2Text2"
- ] ) );
- }
- function testEmpty() {
- $this->assertFilter( "", null );
- }
- function testNonExisting() {
- $this->assertFilter( $this->textId5 + 10, ( $this->textId5 + 10 ) . "\n-1\n" );
- }
- function testNegativeInteger() {
- $this->assertFilter( "-42", "-42\n-1\n" );
- }
- function testFloatingPointNumberExisting() {
- // float -> int -> revision
- $this->assertFilter( $this->textId3 + 0.14159,
- $this->textId3 . "\n23\nFetchTextTestPage2Text2" );
- }
- function testFloatingPointNumberNonExisting() {
- $this->assertFilter( $this->textId5 + 3.14159,
- ( $this->textId5 + 3 ) . "\n-1\n" );
- }
- function testCharacters() {
- $this->assertFilter( "abc", "0\n-1\n" );
- }
- function testMix() {
- $this->assertFilter( "ab\n" . $this->textId4 . ".5cd\n\nefg\n" . $this->textId2
- . "\n" . $this->textId3,
- implode( "", [
- "0\n-1\n",
- $this->textId4 . "\n23\nFetchTextTestPage2Text3",
- "0\n-1\n",
- "0\n-1\n",
- $this->textId2 . "\n23\nFetchTextTestPage2Text1",
- $this->textId3 . "\n23\nFetchTextTestPage2Text2"
- ] ) );
- }
- }
|