aboutsummaryrefslogtreecommitdiffstats
path: root/tests/phpunit/includes/filebackend/FileBackendMultiWriteTest.php
blob: 3bed6c7123b488319035139c0b1e04f8fe788563 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<?php

use MediaWiki\Deferred\DeferredUpdates;
use MediaWiki\WikiMap\WikiMap;
use Wikimedia\FileBackend\FileBackendMultiWrite;
use Wikimedia\FileBackend\MemoryFileBackend;
use Wikimedia\TestingAccessWrapper;

/**
 * @group FileRepo
 * @group FileBackend
 * @covers \Wikimedia\FileBackend\FileBackendMultiWrite
 */
class FileBackendMultiWriteTest extends MediaWikiIntegrationTestCase {
	public function testReadAffinity() {
		$be = TestingAccessWrapper::newFromObject(
			new FileBackendMultiWrite( [
				'name' => 'localtesting',
				'wikiId' => WikiMap::getCurrentWikiId() . mt_rand(),
				'backends' => [
					[ // backend 0
						'name' => 'multitesting0',
						'class' => MemoryFileBackend::class,
						'isMultiMaster' => false,
						'readAffinity' => true
					],
					[ // backend 1
						'name' => 'multitesting1',
						'class' => MemoryFileBackend::class,
						'isMultiMaster' => true
					]
				]
			] )
		);

		$this->assertSame(
			1,
			$be->getReadIndexFromParams( [ 'latest' => 1 ] ),
			'Reads with "latest" flag use backend 1'
		);
		$this->assertSame(
			0,
			$be->getReadIndexFromParams( [ 'latest' => 0 ] ),
			'Reads without "latest" flag use backend 0'
		);

		$p = 'container/test-cont/file.txt';
		$be->backends[0]->quickCreate( [
			'dst' => "mwstore://multitesting0/$p", 'content' => 'cattitude' ] );
		$be->backends[1]->quickCreate( [
			'dst' => "mwstore://multitesting1/$p", 'content' => 'princess of power' ] );

		$this->assertEquals(
			'cattitude',
			$be->getFileContents( [ 'src' => "mwstore://localtesting/$p" ] ),
			"Non-latest read came from backend 0"
		);
		$this->assertEquals(
			'princess of power',
			$be->getFileContents( [ 'src' => "mwstore://localtesting/$p", 'latest' => 1 ] ),
			"Latest read came from backend1"
		);
	}

	public function testAsyncWrites() {
		$deferredUpdates = [];
		$be = TestingAccessWrapper::newFromObject(
			new FileBackendMultiWrite( [
				'name' => 'localtesting',
				'wikiId' => WikiMap::getCurrentWikiId() . mt_rand(),
				'backends' => [
					[ // backend 0
						'name' => 'multitesting0',
						'class' => MemoryFileBackend::class,
						'isMultiMaster' => false
					],
					[ // backend 1
						'name' => 'multitesting1',
						'class' => MemoryFileBackend::class,
						'isMultiMaster' => true
					]
				],
				'replication' => 'async',
				'asyncHandler' => static function ( $update ) use ( &$deferredUpdates ) {
					$deferredUpdates[] = $update;
				}
			] )
		);

		$cleanup = DeferredUpdates::preventOpportunisticUpdates();

		$p = 'container/test-cont/file.txt';
		$be->quickCreate( [
			'dst' => "mwstore://localtesting/$p", 'content' => 'cattitude' ] );

		$this->assertFalse(
			$be->backends[0]->getFileContents( [ 'src' => "mwstore://multitesting0/$p" ] ),
			"File not yet written to backend 0"
		);
		$this->assertEquals(
			'cattitude',
			$be->backends[1]->getFileContents( [ 'src' => "mwstore://multitesting1/$p" ] ),
			"File already written to backend 1"
		);

		foreach ( $deferredUpdates as $update ) {
			$update();
		}

		$this->assertEquals(
			'cattitude',
			$be->backends[0]->getFileContents( [ 'src' => "mwstore://multitesting0/$p" ] ),
			"File now written to backend 0"
		);
	}
}