Merge "Give pages with ~~~~ a different cache TTL"
[lhc/web/wiklou.git] / tests / phpunit / maintenance / backup_LogTest.php
1 <?php
2
3 namespace MediaWiki\Tests\Maintenance;
4
5 use MediaWiki\MediaWikiServices;
6 use DumpBackup;
7 use ManualLogEntry;
8 use Title;
9 use User;
10 use WikiExporter;
11
12 /**
13 * Tests for log dumps of BackupDumper
14 *
15 * Some of these tests use the old constuctor for TextPassDumper
16 * and the dump() function, while others use the new loadWithArgv( $args )
17 * function and execute(). This is to ensure both the old and new methods
18 * work properly.
19 *
20 * @group Database
21 * @group Dump
22 * @covers BackupDumper
23 */
24 class BackupDumperLoggerTest extends DumpTestCase {
25
26 // We'll add several log entries and users for this test. The following
27 // variables hold the corresponding ids.
28 private $userId1, $userId2;
29 private $logId1, $logId2, $logId3;
30
31 /**
32 * adds a log entry to the database.
33 *
34 * @param string $type Type of the log entry
35 * @param string $subtype Subtype of the log entry
36 * @param User $user User that performs the logged operation
37 * @param int $ns Number of the namespace for the entry's target's title
38 * @param string $title Title of the entry's target
39 * @param string $comment Comment of the log entry
40 * @param array $parameters (optional) accompanying data that is attached to the entry
41 *
42 * @return int Id of the added log entry
43 */
44 private function addLogEntry( $type, $subtype, User $user, $ns, $title,
45 $comment = null, $parameters = null
46 ) {
47 $logEntry = new ManualLogEntry( $type, $subtype );
48 $logEntry->setPerformer( $user );
49 $logEntry->setTarget( Title::newFromText( $title, $ns ) );
50 if ( $comment !== null ) {
51 $logEntry->setComment( $comment );
52 }
53 if ( $parameters !== null ) {
54 $logEntry->setParameters( $parameters );
55 }
56
57 return $logEntry->insert();
58 }
59
60 function addDBData() {
61 $this->tablesUsed[] = 'logging';
62 $this->tablesUsed[] = 'user';
63
64 try {
65 $user1 = User::newFromName( 'BackupDumperLogUserA' );
66 $this->userId1 = $user1->getId();
67 if ( $this->userId1 === 0 ) {
68 $user1->addToDatabase();
69 $this->userId1 = $user1->getId();
70 }
71 $this->assertGreaterThan( 0, $this->userId1 );
72
73 $user2 = User::newFromName( 'BackupDumperLogUserB' );
74 $this->userId2 = $user2->getId();
75 if ( $this->userId2 === 0 ) {
76 $user2->addToDatabase();
77 $this->userId2 = $user2->getId();
78 }
79 $this->assertGreaterThan( 0, $this->userId2 );
80
81 $this->logId1 = $this->addLogEntry( 'type', 'subtype',
82 $user1, NS_MAIN, "PageA" );
83 $this->assertGreaterThan( 0, $this->logId1 );
84
85 $this->logId2 = $this->addLogEntry( 'supress', 'delete',
86 $user2, NS_TALK, "PageB", "SomeComment" );
87 $this->assertGreaterThan( 0, $this->logId2 );
88
89 $this->logId3 = $this->addLogEntry( 'move', 'delete',
90 $user2, NS_MAIN, "PageA", "SomeOtherComment",
91 [ 'key1' => 1, 3 => 'value3' ] );
92 $this->assertGreaterThan( 0, $this->logId3 );
93 } catch ( Exception $e ) {
94 // We'd love to pass $e directly. However, ... see
95 // documentation of exceptionFromAddDBData in
96 // DumpTestCase
97 $this->exceptionFromAddDBData = $e;
98 }
99 }
100
101 /**
102 * asserts that the xml reader is at the beginning of a log entry and skips over
103 * it while analyzing it.
104 *
105 * @param int $id Id of the log entry
106 * @param string $user_name User name of the log entry's performer
107 * @param int $user_id User id of the log entry 's performer
108 * @param string|null $comment Comment of the log entry. If null, the comment text is ignored.
109 * @param string $type Type of the log entry
110 * @param string $subtype Subtype of the log entry
111 * @param string $title Title of the log entry's target
112 * @param array $parameters (optional) unserialized data accompanying the log entry
113 */
114 private function assertLogItem( $id, $user_name, $user_id, $comment, $type,
115 $subtype, $title, $parameters = []
116 ) {
117 $this->assertNodeStart( "logitem" );
118 $this->skipWhitespace();
119
120 $this->assertTextNode( "id", $id );
121 $this->assertTextNode( "timestamp", false );
122
123 $this->assertNodeStart( "contributor" );
124 $this->skipWhitespace();
125 $this->assertTextNode( "username", $user_name );
126 $this->assertTextNode( "id", $user_id );
127 $this->assertNodeEnd( "contributor" );
128 $this->skipWhitespace();
129
130 if ( $comment !== null ) {
131 $this->assertTextNode( "comment", $comment );
132 }
133 $this->assertTextNode( "type", $type );
134 $this->assertTextNode( "action", $subtype );
135 $this->assertTextNode( "logtitle", $title );
136
137 $this->assertNodeStart( "params" );
138 $parameters_xml = unserialize( $this->xml->value );
139 $this->assertEquals( $parameters, $parameters_xml );
140 $this->assertTrue( $this->xml->read(), "Skipping past processed text of params" );
141 $this->assertNodeEnd( "params" );
142 $this->skipWhitespace();
143
144 $this->assertNodeEnd( "logitem" );
145 $this->skipWhitespace();
146 }
147
148 function testPlain() {
149 // Preparing the dump
150 $fname = $this->getNewTempFile();
151
152 $dumper = new DumpBackup( [ '--output=file:' . $fname ] );
153 $dumper->startId = $this->logId1;
154 $dumper->endId = $this->logId3 + 1;
155 $dumper->reporting = false;
156 $dumper->setDB( $this->db );
157
158 // Performing the dump
159 $dumper->dump( WikiExporter::LOGS, WikiExporter::TEXT );
160
161 // Analyzing the dumped data
162 $this->assertDumpStart( $fname );
163
164 $this->assertLogItem( $this->logId1, "BackupDumperLogUserA",
165 $this->userId1, null, "type", "subtype", "PageA" );
166
167 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
168 $this->assertNotNull( $contLang, "Content language object validation" );
169 $namespace = $contLang->getNsText( NS_TALK );
170 $this->assertInternalType( 'string', $namespace );
171 $this->assertGreaterThan( 0, strlen( $namespace ) );
172 $this->assertLogItem( $this->logId2, "BackupDumperLogUserB",
173 $this->userId2, "SomeComment", "supress", "delete",
174 $namespace . ":PageB" );
175
176 $this->assertLogItem( $this->logId3, "BackupDumperLogUserB",
177 $this->userId2, "SomeOtherComment", "move", "delete",
178 "PageA", [ 'key1' => 1, 3 => 'value3' ] );
179
180 $this->assertDumpEnd();
181 }
182
183 function testXmlDumpsBackupUseCaseLogging() {
184 $this->checkHasGzip();
185
186 // Preparing the dump
187 $fname = $this->getNewTempFile();
188
189 $dumper = new DumpBackup();
190 $dumper->loadWithArgv( [ '--logs', '--output=gzip:' . $fname,
191 '--reporting=2' ] );
192 $dumper->startId = $this->logId1;
193 $dumper->endId = $this->logId3 + 1;
194 $dumper->setDB( $this->db );
195
196 // xmldumps-backup demands reporting, although this is currently not
197 // implemented in BackupDumper, when dumping logging data. We
198 // nevertheless capture the output of the dump process already now,
199 // to be able to alert (once dumping produces reports) that this test
200 // needs updates.
201 $dumper->stderr = fopen( 'php://output', 'a' );
202 if ( $dumper->stderr === false ) {
203 $this->fail( "Could not open stream for stderr" );
204 }
205
206 // Performing the dump
207 $dumper->execute();
208
209 $this->assertTrue( fclose( $dumper->stderr ), "Closing stderr handle" );
210
211 // Analyzing the dumped data
212 $this->gunzip( $fname );
213
214 $this->assertDumpStart( $fname );
215
216 $this->assertLogItem( $this->logId1, "BackupDumperLogUserA",
217 $this->userId1, null, "type", "subtype", "PageA" );
218
219 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
220 $this->assertNotNull( $contLang, "Content language object validation" );
221 $namespace = $contLang->getNsText( NS_TALK );
222 $this->assertInternalType( 'string', $namespace );
223 $this->assertGreaterThan( 0, strlen( $namespace ) );
224 $this->assertLogItem( $this->logId2, "BackupDumperLogUserB",
225 $this->userId2, "SomeComment", "supress", "delete",
226 $namespace . ":PageB" );
227
228 $this->assertLogItem( $this->logId3, "BackupDumperLogUserB",
229 $this->userId2, "SomeOtherComment", "move", "delete",
230 "PageA", [ 'key1' => 1, 3 => 'value3' ] );
231
232 $this->assertDumpEnd();
233
234 // Currently, no reporting is implemented. Alert via failure, once
235 // this changes.
236 // If reporting for log dumps has been implemented, please update
237 // the following statement to catch good output
238 $this->expectOutputString( '' );
239 }
240 }