3 namespace MediaWiki\Tests\Maintenance
;
12 * Tests for log dumps of BackupDumper
14 * Some of these tests use the old constuctor for TextPassDumper
15 * and the dump() function, while others use the new loadWithArgv( $args )
16 * function and execute(). This is to ensure both the old and new methods
21 * @covers BackupDumper
23 class BackupDumperLoggerTest
extends DumpTestCase
{
25 // We'll add several log entries and users for this test. The following
26 // variables hold the corresponding ids.
27 private $userId1, $userId2;
28 private $logId1, $logId2, $logId3;
31 * adds a log entry to the database.
33 * @param string $type Type of the log entry
34 * @param string $subtype Subtype of the log entry
35 * @param User $user User that performs the logged operation
36 * @param int $ns Number of the namespace for the entry's target's title
37 * @param string $title Title of the entry's target
38 * @param string $comment Comment of the log entry
39 * @param array $parameters (optional) accompanying data that is attached to the entry
41 * @return int Id of the added log entry
43 private function addLogEntry( $type, $subtype, User
$user, $ns, $title,
44 $comment = null, $parameters = null
46 $logEntry = new ManualLogEntry( $type, $subtype );
47 $logEntry->setPerformer( $user );
48 $logEntry->setTarget( Title
::newFromText( $title, $ns ) );
49 if ( $comment !== null ) {
50 $logEntry->setComment( $comment );
52 if ( $parameters !== null ) {
53 $logEntry->setParameters( $parameters );
56 return $logEntry->insert();
59 function addDBData() {
60 $this->tablesUsed
[] = 'logging';
61 $this->tablesUsed
[] = 'user';
64 $user1 = User
::newFromName( 'BackupDumperLogUserA' );
65 $this->userId1
= $user1->getId();
66 if ( $this->userId1
=== 0 ) {
67 $user1->addToDatabase();
68 $this->userId1
= $user1->getId();
70 $this->assertGreaterThan( 0, $this->userId1
);
72 $user2 = User
::newFromName( 'BackupDumperLogUserB' );
73 $this->userId2
= $user2->getId();
74 if ( $this->userId2
=== 0 ) {
75 $user2->addToDatabase();
76 $this->userId2
= $user2->getId();
78 $this->assertGreaterThan( 0, $this->userId2
);
80 $this->logId1
= $this->addLogEntry( 'type', 'subtype',
81 $user1, NS_MAIN
, "PageA" );
82 $this->assertGreaterThan( 0, $this->logId1
);
84 $this->logId2
= $this->addLogEntry( 'supress', 'delete',
85 $user2, NS_TALK
, "PageB", "SomeComment" );
86 $this->assertGreaterThan( 0, $this->logId2
);
88 $this->logId3
= $this->addLogEntry( 'move', 'delete',
89 $user2, NS_MAIN
, "PageA", "SomeOtherComment",
90 [ 'key1' => 1, 3 => 'value3' ] );
91 $this->assertGreaterThan( 0, $this->logId3
);
92 } catch ( Exception
$e ) {
93 // We'd love to pass $e directly. However, ... see
94 // documentation of exceptionFromAddDBData in
96 $this->exceptionFromAddDBData
= $e;
101 * asserts that the xml reader is at the beginning of a log entry and skips over
102 * it while analyzing it.
104 * @param int $id Id of the log entry
105 * @param string $user_name User name of the log entry's performer
106 * @param int $user_id User id of the log entry 's performer
107 * @param string|null $comment Comment of the log entry. If null, the comment text is ignored.
108 * @param string $type Type of the log entry
109 * @param string $subtype Subtype of the log entry
110 * @param string $title Title of the log entry's target
111 * @param array $parameters (optional) unserialized data accompanying the log entry
113 private function assertLogItem( $id, $user_name, $user_id, $comment, $type,
114 $subtype, $title, $parameters = []
116 $this->assertNodeStart( "logitem" );
117 $this->skipWhitespace();
119 $this->assertTextNode( "id", $id );
120 $this->assertTextNode( "timestamp", false );
122 $this->assertNodeStart( "contributor" );
123 $this->skipWhitespace();
124 $this->assertTextNode( "username", $user_name );
125 $this->assertTextNode( "id", $user_id );
126 $this->assertNodeEnd( "contributor" );
127 $this->skipWhitespace();
129 if ( $comment !== null ) {
130 $this->assertTextNode( "comment", $comment );
132 $this->assertTextNode( "type", $type );
133 $this->assertTextNode( "action", $subtype );
134 $this->assertTextNode( "logtitle", $title );
136 $this->assertNodeStart( "params" );
137 $parameters_xml = unserialize( $this->xml
->value
);
138 $this->assertEquals( $parameters, $parameters_xml );
139 $this->assertTrue( $this->xml
->read(), "Skipping past processed text of params" );
140 $this->assertNodeEnd( "params" );
141 $this->skipWhitespace();
143 $this->assertNodeEnd( "logitem" );
144 $this->skipWhitespace();
147 function testPlain() {
150 // Preparing the dump
151 $fname = $this->getNewTempFile();
153 $dumper = new DumpBackup( [ '--output=file:' . $fname ] );
154 $dumper->startId
= $this->logId1
;
155 $dumper->endId
= $this->logId3 +
1;
156 $dumper->reporting
= false;
157 $dumper->setDB( $this->db
);
159 // Performing the dump
160 $dumper->dump( WikiExporter
::LOGS
, WikiExporter
::TEXT
);
162 // Analyzing the dumped data
163 $this->assertDumpStart( $fname );
165 $this->assertLogItem( $this->logId1
, "BackupDumperLogUserA",
166 $this->userId1
, null, "type", "subtype", "PageA" );
168 $this->assertNotNull( $wgContLang, "Content language object validation" );
169 $namespace = $wgContLang->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" );
176 $this->assertLogItem( $this->logId3
, "BackupDumperLogUserB",
177 $this->userId2
, "SomeOtherComment", "move", "delete",
178 "PageA", [ 'key1' => 1, 3 => 'value3' ] );
180 $this->assertDumpEnd();
183 function testXmlDumpsBackupUseCaseLogging() {
186 $this->checkHasGzip();
188 // Preparing the dump
189 $fname = $this->getNewTempFile();
191 $dumper = new DumpBackup();
192 $dumper->loadWithArgv( [ '--logs', '--output=gzip:' . $fname,
194 $dumper->startId
= $this->logId1
;
195 $dumper->endId
= $this->logId3 +
1;
196 $dumper->setDB( $this->db
);
198 // xmldumps-backup demands reporting, although this is currently not
199 // implemented in BackupDumper, when dumping logging data. We
200 // nevertheless capture the output of the dump process already now,
201 // to be able to alert (once dumping produces reports) that this test
203 $dumper->stderr
= fopen( 'php://output', 'a' );
204 if ( $dumper->stderr
=== false ) {
205 $this->fail( "Could not open stream for stderr" );
208 // Performing the dump
211 $this->assertTrue( fclose( $dumper->stderr
), "Closing stderr handle" );
213 // Analyzing the dumped data
214 $this->gunzip( $fname );
216 $this->assertDumpStart( $fname );
218 $this->assertLogItem( $this->logId1
, "BackupDumperLogUserA",
219 $this->userId1
, null, "type", "subtype", "PageA" );
221 $this->assertNotNull( $wgContLang, "Content language object validation" );
222 $namespace = $wgContLang->getNsText( NS_TALK
);
223 $this->assertInternalType( 'string', $namespace );
224 $this->assertGreaterThan( 0, strlen( $namespace ) );
225 $this->assertLogItem( $this->logId2
, "BackupDumperLogUserB",
226 $this->userId2
, "SomeComment", "supress", "delete",
227 $namespace . ":PageB" );
229 $this->assertLogItem( $this->logId3
, "BackupDumperLogUserB",
230 $this->userId2
, "SomeOtherComment", "move", "delete",
231 "PageA", [ 'key1' => 1, 3 => 'value3' ] );
233 $this->assertDumpEnd();
235 // Currently, no reporting is implemented. Alert via failure, once
237 // If reporting for log dumps has been implemented, please update
238 // the following statement to catch good output
239 $this->expectOutputString( '' );