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