Merge "RevisionStoreDbTestBase, remove redundant needsDB override"
[lhc/web/wiklou.git] / tests / phpunit / includes / Storage / RevisionSlotsUpdateTest.php
1 <?php
2
3 namespace MediaWiki\Tests\Storage;
4
5 use Content;
6 use MediaWiki\Storage\MutableRevisionSlots;
7 use MediaWiki\Storage\RevisionSlots;
8 use MediaWiki\Storage\RevisionSlotsUpdate;
9 use MediaWiki\Storage\RevisionAccessException;
10 use MediaWiki\Storage\SlotRecord;
11 use MediaWikiTestCase;
12 use WikitextContent;
13
14 /**
15 * @covers \MediaWiki\Storage\RevisionSlotsUpdate
16 */
17 class RevisionSlotsUpdateTest extends MediaWikiTestCase {
18
19 public function provideNewFromRevisionSlots() {
20 $slotA = SlotRecord::newUnsaved( 'A', new WikitextContent( 'A' ) );
21 $slotB = SlotRecord::newUnsaved( 'B', new WikitextContent( 'B' ) );
22 $slotC = SlotRecord::newUnsaved( 'C', new WikitextContent( 'C' ) );
23
24 $slotB2 = SlotRecord::newUnsaved( 'B', new WikitextContent( 'B2' ) );
25
26 $parentSlots = new RevisionSlots( [
27 'A' => $slotA,
28 'B' => $slotB,
29 'C' => $slotC,
30 ] );
31
32 $newSlots = new RevisionSlots( [
33 'A' => $slotA,
34 'B' => $slotB2,
35 ] );
36
37 yield [ $newSlots, null, [ 'A', 'B' ], [] ];
38 yield [ $newSlots, $parentSlots, [ 'B' ], [ 'C' ] ];
39 }
40
41 /**
42 * @dataProvider provideNewFromRevisionSlots
43 *
44 * @param RevisionSlots $newSlots
45 * @param RevisionSlots $parentSlots
46 * @param string[] $modified
47 * @param string[] $removed
48 */
49 public function testNewFromRevisionSlots(
50 RevisionSlots $newSlots,
51 RevisionSlots $parentSlots = null,
52 array $modified = [],
53 array $removed = []
54 ) {
55 $update = RevisionSlotsUpdate::newFromRevisionSlots( $newSlots, $parentSlots );
56
57 $this->assertEquals( $modified, $update->getModifiedRoles() );
58 $this->assertEquals( $removed, $update->getRemovedRoles() );
59
60 foreach ( $modified as $role ) {
61 $this->assertSame( $newSlots->getSlot( $role ), $update->getModifiedSlot( $role ) );
62 }
63 }
64
65 public function provideNewFromContent() {
66 $slotA = SlotRecord::newUnsaved( 'A', new WikitextContent( 'A' ) );
67 $slotB = SlotRecord::newUnsaved( 'B', new WikitextContent( 'B' ) );
68 $slotC = SlotRecord::newUnsaved( 'C', new WikitextContent( 'C' ) );
69
70 $parentSlots = new RevisionSlots( [
71 'A' => $slotA,
72 'B' => $slotB,
73 'C' => $slotC,
74 ] );
75
76 $newContent = [
77 'A' => new WikitextContent( 'A' ),
78 'B' => new WikitextContent( 'B2' ),
79 ];
80
81 yield [ $newContent, null, [ 'A', 'B' ] ];
82 yield [ $newContent, $parentSlots, [ 'B' ] ];
83 }
84
85 /**
86 * @dataProvider provideNewFromContent
87 *
88 * @param Content[] $newContent
89 * @param RevisionSlots $parentSlots
90 * @param string[] $modified
91 */
92 public function testNewFromContent(
93 array $newContent,
94 RevisionSlots $parentSlots = null,
95 array $modified = []
96 ) {
97 $update = RevisionSlotsUpdate::newFromContent( $newContent, $parentSlots );
98
99 $this->assertEquals( $modified, $update->getModifiedRoles() );
100 $this->assertEmpty( $update->getRemovedRoles() );
101 }
102
103 public function testConstructor() {
104 $update = new RevisionSlotsUpdate();
105
106 $this->assertEmpty( $update->getModifiedRoles() );
107 $this->assertEmpty( $update->getRemovedRoles() );
108
109 $slotA = SlotRecord::newUnsaved( 'A', new WikitextContent( 'A' ) );
110 $update = new RevisionSlotsUpdate( [ 'A' => $slotA ] );
111
112 $this->assertEquals( [ 'A' ], $update->getModifiedRoles() );
113 $this->assertEmpty( $update->getRemovedRoles() );
114
115 $update = new RevisionSlotsUpdate( [ 'A' => $slotA ], [ 'X' ] );
116
117 $this->assertEquals( [ 'A' ], $update->getModifiedRoles() );
118 $this->assertEquals( [ 'X' ], $update->getRemovedRoles() );
119 }
120
121 public function testModifySlot() {
122 $slots = new RevisionSlotsUpdate();
123
124 $this->assertSame( [], $slots->getModifiedRoles() );
125 $this->assertSame( [], $slots->getRemovedRoles() );
126
127 $slotA = SlotRecord::newUnsaved( 'some', new WikitextContent( 'A' ) );
128 $slots->modifySlot( $slotA );
129 $this->assertTrue( $slots->isModifiedSlot( 'some' ) );
130 $this->assertFalse( $slots->isRemovedSlot( 'some' ) );
131 $this->assertSame( $slotA, $slots->getModifiedSlot( 'some' ) );
132 $this->assertSame( [ 'some' ], $slots->getModifiedRoles() );
133 $this->assertSame( [], $slots->getRemovedRoles() );
134
135 $slotB = SlotRecord::newUnsaved( 'other', new WikitextContent( 'B' ) );
136 $slots->modifySlot( $slotB );
137 $this->assertTrue( $slots->isModifiedSlot( 'other' ) );
138 $this->assertFalse( $slots->isRemovedSlot( 'other' ) );
139 $this->assertSame( $slotB, $slots->getModifiedSlot( 'other' ) );
140 $this->assertSame( [ 'some', 'other' ], $slots->getModifiedRoles() );
141 $this->assertSame( [], $slots->getRemovedRoles() );
142
143 // modify slot A again
144 $slots->modifySlot( $slotA );
145 $this->assertArrayEquals( [ 'some', 'other' ], $slots->getModifiedRoles() );
146
147 // remove modified slot
148 $slots->removeSlot( 'some' );
149 $this->assertSame( [ 'other' ], $slots->getModifiedRoles() );
150 $this->assertSame( [ 'some' ], $slots->getRemovedRoles() );
151
152 // modify removed slot
153 $slots->modifySlot( $slotA );
154 $this->assertArrayEquals( [ 'some', 'other' ], $slots->getModifiedRoles() );
155 $this->assertSame( [], $slots->getRemovedRoles() );
156 }
157
158 public function testRemoveSlot() {
159 $slots = new RevisionSlotsUpdate();
160
161 $slotA = SlotRecord::newUnsaved( 'main', new WikitextContent( 'A' ) );
162 $slots->modifySlot( $slotA );
163
164 $this->assertSame( [ 'main' ], $slots->getModifiedRoles() );
165
166 $slots->removeSlot( 'main' );
167 $slots->removeSlot( 'other' );
168 $this->assertSame( [], $slots->getModifiedRoles() );
169 $this->assertSame( [ 'main', 'other' ], $slots->getRemovedRoles() );
170 $this->assertTrue( $slots->isRemovedSlot( 'main' ) );
171 $this->assertTrue( $slots->isRemovedSlot( 'other' ) );
172 $this->assertFalse( $slots->isModifiedSlot( 'main' ) );
173
174 // removing the same slot again should not trigger an error
175 $slots->removeSlot( 'main' );
176
177 // getting a slot after removing it should fail
178 $this->setExpectedException( RevisionAccessException::class );
179 $slots->getModifiedSlot( 'main' );
180 }
181
182 public function testGetModifiedRoles() {
183 $slots = new RevisionSlotsUpdate( [], [ 'xyz' ] );
184
185 $this->assertSame( [], $slots->getModifiedRoles() );
186
187 $slots->modifyContent( 'main', new WikitextContent( 'A' ) );
188 $slots->modifyContent( 'foo', new WikitextContent( 'Foo' ) );
189 $this->assertSame( [ 'main', 'foo' ], $slots->getModifiedRoles() );
190
191 $slots->removeSlot( 'main' );
192 $this->assertSame( [ 'foo' ], $slots->getModifiedRoles() );
193 }
194
195 public function testGetRemovedRoles() {
196 $slotA = SlotRecord::newUnsaved( 'main', new WikitextContent( 'A' ) );
197 $slots = new RevisionSlotsUpdate( [ $slotA ] );
198
199 $this->assertSame( [], $slots->getRemovedRoles() );
200
201 $slots->removeSlot( 'main', new WikitextContent( 'A' ) );
202 $slots->removeSlot( 'foo', new WikitextContent( 'Foo' ) );
203
204 $this->assertSame( [ 'main', 'foo' ], $slots->getRemovedRoles() );
205
206 $slots->modifyContent( 'main', new WikitextContent( 'A' ) );
207 $this->assertSame( [ 'foo' ], $slots->getRemovedRoles() );
208 }
209
210 public function provideHasSameUpdates() {
211 $fooX = SlotRecord::newUnsaved( 'x', new WikitextContent( 'Foo' ) );
212 $barZ = SlotRecord::newUnsaved( 'z', new WikitextContent( 'Bar' ) );
213
214 $a = new RevisionSlotsUpdate();
215 $a->modifySlot( $fooX );
216 $a->modifySlot( $barZ );
217 $a->removeSlot( 'Q' );
218
219 $a2 = new RevisionSlotsUpdate();
220 $a2->modifySlot( $fooX );
221 $a2->modifySlot( $barZ );
222 $a2->removeSlot( 'Q' );
223
224 $b = new RevisionSlotsUpdate();
225 $b->modifySlot( $barZ );
226 $b->removeSlot( 'Q' );
227
228 $c = new RevisionSlotsUpdate();
229 $c->modifySlot( $fooX );
230 $c->modifySlot( $barZ );
231
232 yield 'same instance' => [ $a, $a, true ];
233 yield 'same udpates' => [ $a, $a2, true ];
234
235 yield 'different modified' => [ $a, $b, false ];
236 yield 'different removed' => [ $a, $c, false ];
237 }
238
239 /**
240 * @dataProvider provideHasSameUpdates
241 */
242 public function testHasSameUpdates( RevisionSlotsUpdate $a, RevisionSlotsUpdate $b, $same ) {
243 $this->assertSame( $same, $a->hasSameUpdates( $b ) );
244 $this->assertSame( $same, $b->hasSameUpdates( $a ) );
245 }
246
247 /**
248 * @param string $role
249 * @param Content $content
250 * @return SlotRecord
251 */
252 private function newSavedSlot( $role, Content $content ) {
253 return SlotRecord::newSaved( 7, 7, 'xyz', SlotRecord::newUnsaved( $role, $content ) );
254 }
255
256 public function testApplyUpdate() {
257 /** @var SlotRecord[] $parentSlots */
258 $parentSlots = [
259 'X' => $this->newSavedSlot( 'X', new WikitextContent( 'X' ) ),
260 'Y' => $this->newSavedSlot( 'Y', new WikitextContent( 'Y' ) ),
261 'Z' => $this->newSavedSlot( 'Z', new WikitextContent( 'Z' ) ),
262 ];
263 $slots = MutableRevisionSlots::newFromParentRevisionSlots( $parentSlots );
264 $update = RevisionSlotsUpdate::newFromContent( [
265 'A' => new WikitextContent( 'A' ),
266 'Y' => new WikitextContent( 'yyy' ),
267 ] );
268
269 $update->removeSlot( 'Z' );
270
271 $update->apply( $slots );
272 $this->assertSame( [ 'X', 'Y', 'A' ], $slots->getSlotRoles() );
273 $this->assertSame( $update->getModifiedSlot( 'A' ), $slots->getSlot( 'A' ) );
274 $this->assertSame( $update->getModifiedSlot( 'Y' ), $slots->getSlot( 'Y' ) );
275 }
276
277 }