Merge "(bug 43211) Remove unneeded noprint classes after CSS change."
[lhc/web/wiklou.git] / tests / phpunit / maintenance / fetchTextTest.php
1 <?php
2
3 require_once __DIR__ . "/../../../maintenance/fetchText.php";
4
5 /**
6 * Mock for the input/output of FetchText
7 *
8 * FetchText internally tries to access stdin and stdout. We mock those aspects
9 * for testing.
10 */
11 class SemiMockedFetchText extends FetchText {
12
13 /**
14 * @var String|null Text to pass as stdin
15 */
16 private $mockStdinText = null;
17
18 /**
19 * @var bool Whether or not a text for stdin has been provided
20 */
21 private $mockSetUp = false;
22
23 /**
24 * @var Array Invocation counters for the mocked aspects
25 */
26 private $mockInvocations = array( 'getStdin' => 0 );
27
28
29
30 /**
31 * Data for the fake stdin
32 *
33 * @param $stdin String The string to be used instead of stdin
34 */
35 function mockStdin( $stdin ) {
36 $this->mockStdinText = $stdin;
37 $this->mockSetUp = true;
38 }
39
40 /**
41 * Gets invocation counters for mocked methods.
42 *
43 * @return Array An array, whose keys are function names. The corresponding values
44 * denote the number of times the function has been invoked.
45 */
46 function mockGetInvocations() {
47 return $this->mockInvocations;
48 }
49
50 // -----------------------------------------------------------------
51 // Mocked functions from FetchText follow.
52
53 function getStdin( $len = null ) {
54 $this->mockInvocations['getStdin']++;
55 if ( $len !== null ) {
56 throw new PHPUnit_Framework_ExpectationFailedException(
57 "Tried to get stdin with non null parameter" );
58 }
59
60 if ( ! $this->mockSetUp ) {
61 throw new PHPUnit_Framework_ExpectationFailedException(
62 "Tried to get stdin before setting up rerouting" );
63 }
64
65 return fopen( 'data://text/plain,' . $this->mockStdinText, 'r' );
66 }
67
68 }
69
70 /**
71 * TestCase for FetchText
72 *
73 * @group Database
74 * @group Dump
75 */
76 class FetchTextTest extends MediaWikiTestCase {
77
78 // We add 5 Revisions for this test. Their corresponding text id's
79 // are stored in the following 5 variables.
80 private $textId1;
81 private $textId2;
82 private $textId3;
83 private $textId4;
84 private $textId5;
85
86
87 /**
88 * @var Exception|null As the current MediaWikiTestCase::run is not
89 * robust enough to recover from thrown exceptions directly, we cannot
90 * throw frow within addDBData, although it would be appropriate. Hence,
91 * we catch the exception and store it until we are in setUp and may
92 * finally rethrow the exception without crashing the test suite.
93 */
94 private $exceptionFromAddDBData;
95
96 /**
97 * @var FetchText the (mocked) FetchText that is to test
98 */
99 private $fetchText;
100
101 /**
102 * Adds a revision to a page, while returning the resuting text's id
103 *
104 * @param $page WikiPage The page to add the revision to
105 * @param $text String The revisions text
106 * @param $text String The revisions summare
107 *
108 * @throws MWExcepion
109 */
110 private function addRevision( $page, $text, $summary ) {
111 $status = $page->doEditContent( ContentHandler::makeContent( $text, $page->getTitle() ), $summary );
112 if ( $status->isGood() ) {
113 $value = $status->getValue();
114 $revision = $value['revision'];
115 $id = $revision->getTextId();
116 if ( $id > 0 ) {
117 return $id;
118 }
119 }
120 throw new MWException( "Could not determine text id" );
121 }
122
123
124 function addDBData() {
125 $this->tablesUsed[] = 'page';
126 $this->tablesUsed[] = 'revision';
127 $this->tablesUsed[] = 'text';
128
129 $wikitextNamespace = $this->getDefaultWikitextNS();
130
131 try {
132 $title = Title::newFromText( 'FetchTextTestPage1', $wikitextNamespace );
133 $page = WikiPage::factory( $title );
134 $this->textId1 = $this->addRevision( $page, "FetchTextTestPage1Text1", "FetchTextTestPage1Summary1" );
135
136 $title = Title::newFromText( 'FetchTextTestPage2', $wikitextNamespace );
137 $page = WikiPage::factory( $title );
138 $this->textId2 = $this->addRevision( $page, "FetchTextTestPage2Text1", "FetchTextTestPage2Summary1" );
139 $this->textId3 = $this->addRevision( $page, "FetchTextTestPage2Text2", "FetchTextTestPage2Summary2" );
140 $this->textId4 = $this->addRevision( $page, "FetchTextTestPage2Text3", "FetchTextTestPage2Summary3" );
141 $this->textId5 = $this->addRevision( $page, "FetchTextTestPage2Text4 some additional Text ", "FetchTextTestPage2Summary4 extra " );
142 } catch ( Exception $e ) {
143 // We'd love to pass $e directly. However, ... see
144 // documentation of exceptionFromAddDBData
145 $this->exceptionFromAddDBData = $e;
146 }
147 }
148
149
150 protected function setUp() {
151 parent::setUp();
152
153 // Check if any Exception is stored for rethrowing from addDBData
154 if ( $this->exceptionFromAddDBData !== null ) {
155 throw $this->exceptionFromAddDBData;
156 }
157
158 $this->fetchText = new SemiMockedFetchText();
159 }
160
161
162 /**
163 * Helper to relate FetchText's input and output
164 */
165 private function assertFilter( $input, $expectedOutput ) {
166 $this->fetchText->mockStdin( $input );
167 $this->fetchText->execute();
168 $invocations = $this->fetchText->mockGetInvocations();
169 $this->assertEquals( 1, $invocations['getStdin'],
170 "getStdin invocation counter" );
171 $this->expectOutputString( $expectedOutput );
172 }
173
174
175
176 // Instead of the following functions, a data provider would be great.
177 // However, as data providers are evaluated /before/ addDBData, a data
178 // provider would not know the required ids.
179
180 function testExistingSimple() {
181 $this->assertFilter( $this->textId2,
182 $this->textId2 . "\n23\nFetchTextTestPage2Text1" );
183 }
184
185 function testExistingSimpleWithNewline() {
186 $this->assertFilter( $this->textId2 . "\n",
187 $this->textId2 . "\n23\nFetchTextTestPage2Text1" );
188 }
189
190 function testExistingSeveral() {
191 $this->assertFilter( "$this->textId1\n$this->textId5\n"
192 . "$this->textId3\n$this->textId3",
193 implode( "", array(
194 $this->textId1 . "\n23\nFetchTextTestPage1Text1",
195 $this->textId5 . "\n44\nFetchTextTestPage2Text4 "
196 . "some additional Text",
197 $this->textId3 . "\n23\nFetchTextTestPage2Text2",
198 $this->textId3 . "\n23\nFetchTextTestPage2Text2"
199 ) ) );
200 }
201
202 function testEmpty() {
203 $this->assertFilter( "", null );
204 }
205
206 function testNonExisting() {
207 $this->assertFilter( $this->textId5 + 10, ( $this->textId5 + 10 ) . "\n-1\n" );
208 }
209
210 function testNegativeInteger() {
211 $this->assertFilter( "-42", "-42\n-1\n" );
212 }
213
214 function testFloatingPointNumberExisting() {
215 // float -> int -> revision
216 $this->assertFilter( $this->textId3 + 0.14159,
217 $this->textId3 . "\n23\nFetchTextTestPage2Text2" );
218 }
219
220 function testFloatingPointNumberNonExisting() {
221 $this->assertFilter( $this->textId5 + 3.14159,
222 ( $this->textId5 + 3 ) . "\n-1\n" );
223 }
224
225 function testCharacters() {
226 $this->assertFilter( "abc", "0\n-1\n" );
227 }
228
229 function testMix() {
230 $this->assertFilter( "ab\n" . $this->textId4 . ".5cd\n\nefg\n" . $this->textId2
231 . "\n" . $this->textId3,
232 implode( "", array(
233 "0\n-1\n",
234 $this->textId4 . "\n23\nFetchTextTestPage2Text3",
235 "0\n-1\n",
236 "0\n-1\n",
237 $this->textId2 . "\n23\nFetchTextTestPage2Text1",
238 $this->textId3 . "\n23\nFetchTextTestPage2Text2"
239 ) ) );
240 }
241
242 }