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