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