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