Merge "Type hint against LinkTarget in WatchedItemStore"
[lhc/web/wiklou.git] / tests / phpunit / includes / Revision / McrWriteBothRevisionStoreDbTest.php
1 <?php
2
3 namespace MediaWiki\Tests\Revision;
4
5 use InvalidArgumentException;
6 use MediaWiki\MediaWikiServices;
7 use MediaWiki\Revision\RevisionRecord;
8 use MediaWiki\Revision\SlotRecord;
9 use Revision;
10 use WikitextContent;
11
12 /**
13 * Tests RevisionStore against the intermediate MCR DB schema for use during schema migration.
14 *
15 * @covers \MediaWiki\Revision\RevisionStore
16 *
17 * @group RevisionStore
18 * @group Storage
19 * @group Database
20 * @group medium
21 */
22 class McrWriteBothRevisionStoreDbTest extends RevisionStoreDbTestBase {
23
24 use McrWriteBothSchemaOverride;
25
26 protected function revisionToRow( Revision $rev, $options = [ 'page', 'user', 'comment' ] ) {
27 $row = parent::revisionToRow( $rev, $options );
28
29 $row->rev_text_id = (string)$rev->getTextId();
30 $row->rev_content_format = (string)$rev->getContentFormat();
31 $row->rev_content_model = (string)$rev->getContentModel();
32
33 return $row;
34 }
35
36 protected function assertRevisionExistsInDatabase( RevisionRecord $rev ) {
37 // New schema is being written
38 $this->assertSelect(
39 'slots',
40 [ 'count(*)' ],
41 [ 'slot_revision_id' => $rev->getId() ],
42 [ [ '1' ] ]
43 );
44
45 $this->assertSelect(
46 'content',
47 [ 'count(*)' ],
48 [ 'content_address' => $rev->getSlot( 'main' )->getAddress() ],
49 [ [ '1' ] ]
50 );
51
52 // Legacy schema is still being written
53 $this->assertSelect(
54 [ 'revision', 'text' ],
55 [ 'count(*)' ],
56 [ 'rev_id' => $rev->getId(), 'rev_text_id > 0' ],
57 [ [ 1 ] ],
58 [],
59 [ 'text' => [ 'JOIN', [ 'rev_text_id = old_id' ] ] ]
60 );
61
62 parent::assertRevisionExistsInDatabase( $rev );
63 }
64
65 /**
66 * @param SlotRecord $a
67 * @param SlotRecord $b
68 */
69 protected function assertSameSlotContent( SlotRecord $a, SlotRecord $b ) {
70 parent::assertSameSlotContent( $a, $b );
71
72 // Assert that the same content ID has been used
73 if ( $a->hasContentId() && $b->hasContentId() ) {
74 $this->assertSame( $a->getContentId(), $b->getContentId() );
75 }
76 }
77
78 public function provideInsertRevisionOn_failures() {
79 foreach ( parent::provideInsertRevisionOn_failures() as $case ) {
80 yield $case;
81 }
82
83 yield 'slot that is not main slot' => [
84 [
85 'content' => [
86 'main' => new WikitextContent( 'Chicken' ),
87 'lalala' => new WikitextContent( 'Duck' ),
88 ],
89 'comment' => $this->getRandomCommentStoreComment(),
90 'timestamp' => '20171117010101',
91 'user' => true,
92 ],
93 new InvalidArgumentException( 'Only the main slot is supported' )
94 ];
95 }
96
97 public function provideNewMutableRevisionFromArray() {
98 foreach ( parent::provideNewMutableRevisionFromArray() as $case ) {
99 yield $case;
100 }
101
102 yield 'Basic array, with page & id' => [
103 [
104 'id' => 2,
105 'page' => 1,
106 'text_id' => 2,
107 'timestamp' => '20171017114835',
108 'user_text' => '111.0.1.2',
109 'user' => 0,
110 'minor_edit' => false,
111 'deleted' => 0,
112 'len' => 46,
113 'parent_id' => 1,
114 'sha1' => 'rdqbbzs3pkhihgbs8qf2q9jsvheag5z',
115 'comment' => 'Goat Comment!',
116 'content_format' => 'text/x-wiki',
117 'content_model' => 'wikitext',
118 ]
119 ];
120 }
121
122 /**
123 * @covers \MediaWiki\Revision\RevisionStore::newRevisionFromArchiveRow
124 * @covers \MediaWiki\Revision\RevisionStore::insertRevisionOn
125 */
126 public function testInsertRevisionFromArchiveRow_unmigratedArchiveRow() {
127 // The main purpose of this test is to assert that after reading an archive
128 // row using the old schema it can be inserted into the revision table,
129 // and a slot row is created based on slot emulated from the old-style archive row,
130 // when none such slot row exists yet.
131
132 $title = $this->getTestPage()->getTitle();
133
134 $this->db->insert(
135 'text',
136 [ 'old_text' => 'Just a test', 'old_flags' => 'utf-8' ],
137 __METHOD__
138 );
139
140 $textId = $this->db->insertId();
141
142 $row = (object)[
143 'ar_minor_edit' => '0',
144 'ar_user' => '0',
145 'ar_user_text' => '127.0.0.1',
146 'ar_actor' => null,
147 'ar_len' => '11',
148 'ar_deleted' => '0',
149 'ar_rev_id' => 112277,
150 'ar_timestamp' => $this->db->timestamp( '20180101000000' ),
151 'ar_sha1' => 'deadbeef',
152 'ar_page_id' => $title->getArticleID(),
153 'ar_comment_text' => 'just a test',
154 'ar_comment_data' => null,
155 'ar_comment_cid' => null,
156 'ar_content_format' => null,
157 'ar_content_model' => null,
158 'ts_tags' => null,
159 'ar_id' => 17,
160 'ar_namespace' => $title->getNamespace(),
161 'ar_title' => $title->getDBkey(),
162 'ar_text_id' => $textId,
163 'ar_parent_id' => 112211,
164 ];
165
166 $store = MediaWikiServices::getInstance()->getRevisionStore();
167 $rev = $store->newRevisionFromArchiveRow( $row );
168
169 // re-insert archived revision
170 $return = $store->insertRevisionOn( $rev, $this->db );
171
172 // is the new revision correct?
173 $this->assertRevisionCompleteness( $return );
174 $this->assertRevisionRecordsEqual( $rev, $return );
175
176 // can we load it from the store?
177 $loaded = $store->getRevisionById( $return->getId() );
178 $this->assertNotNull( $loaded );
179 $this->assertRevisionCompleteness( $loaded );
180 $this->assertRevisionRecordsEqual( $return, $loaded );
181
182 // can we find it directly in the database?
183 $this->assertRevisionExistsInDatabase( $return );
184 }
185
186 /**
187 * Conditions to use together with getSlotsQueryInfo() when selecting slot rows for a given
188 * revision.
189 *
190 * @return array
191 */
192 protected function getSlotRevisionConditions( $revId ) {
193 return [ 'rev_id' => $revId ];
194 }
195
196 }