49 ->disableOriginalConstructor()
53 'class' => $deprecated,
54 'connection' => $mockDB,
55 # Various other parameters required:
58 'serverTemplate' => [],
61 $this->
hideDeprecated(
'$wgLBFactoryConf must be updated. See RELEASE-NOTES for details' );
64 $this->assertEquals( $expected,
$result );
69 # Format: new class, old class
100 $lb = $factory->getMainLB();
103 $this->assertTrue( $dbw->getLBInfo(
'master' ),
'master shows as master' );
106 $this->assertTrue(
$dbr->getLBInfo(
'master' ),
'DB_REPLICA also gets the master' );
108 $this->assertSame(
'my_test_wiki', $factory->resolveDomainID(
'my_test_wiki' ) );
109 $this->assertSame( $factory->getLocalDomainID(), $factory->resolveDomainID(
false ) );
111 $factory->shutdown();
142 'servers' => $servers,
145 $lb = $factory->getMainLB();
148 $this->assertTrue( $dbw->getLBInfo(
'master' ),
'master shows as master' );
151 $dbw->getLBInfo(
'clusterMasterHost' ),
152 'cluster master set' );
155 $this->assertTrue(
$dbr->getLBInfo(
'replica' ),
'slave shows as slave' );
158 $dbr->getLBInfo(
'clusterMasterHost' ),
159 'cluster master set' );
161 $factory->shutdown();
168 $dbw = $factory->getMainLB()->getConnection(
DB_MASTER );
169 $this->assertTrue( $dbw->getLBInfo(
'master' ),
'master shows as master' );
172 $this->assertTrue(
$dbr->getLBInfo(
'replica' ),
'slave shows as slave' );
182 $factory->forEachLB(
function ()
use ( &$count ) {
190 $this->assertEquals( 0, $countLBsFunc( $factory ) );
191 $dbw = $factory->getMainLB()->getConnection(
DB_MASTER );
192 $this->assertEquals( 1, $countLBsFunc( $factory ) );
195 $factory->beginMasterChanges( __METHOD__ );
196 $dbw->onTransactionPreCommitOrIdle(
function ()
use ( $factory, &
$called ) {
201 $factory->getMainLB(
's1wiki' )->getConnection(
DB_MASTER );
203 $factory->commitMasterChanges( __METHOD__ );
204 $this->assertEquals( 1,
$called );
205 $this->assertEquals( 2, $countLBsFunc( $factory ) );
206 $factory->shutdown();
207 $factory->closeAll();
211 $this->assertEquals( 0, $countLBsFunc( $factory ) );
212 $dbw = $factory->getMainLB()->getConnection(
DB_MASTER );
213 $this->assertEquals( 1, $countLBsFunc( $factory ) );
217 $factory->beginMasterChanges( __METHOD__ );
218 $dbw->query(
"SELECT 1 as t", __METHOD__ );
219 $dbw->onTransactionResolution(
function ()
use ( $factory, &
$called ) {
224 $factory->getMainLB(
's1wiki' )->getConnection(
DB_MASTER );
226 $factory->commitMasterChanges( __METHOD__ );
227 $this->assertEquals( 1,
$called );
228 $this->assertEquals( 2, $countLBsFunc( $factory ) );
229 $factory->shutdown();
230 $factory->closeAll();
233 $dbw = $factory->getMainLB()->getConnection(
DB_MASTER );
236 $dbw->onTransactionPreCommitOrIdle(
function ()
use ( &$ran ) {
239 $factory->commitAll( __METHOD__ );
240 $this->assertEquals( 1, $ran );
242 $factory->shutdown();
243 $factory->closeAll();
263 'serverTemplate' => [
285 $now = microtime(
true );
288 $m1Pos =
new MySQLMasterPos(
'db1034-bin.000976/843431247', $now );
289 $m2Pos =
new MySQLMasterPos(
'db1064-bin.002400/794074907', $now );
293 ->disableOriginalConstructor()
295 $mockDB1->method(
'writesOrCallbacksPending' )->willReturn(
true );
296 $mockDB1->method(
'lastDoneWrites' )->willReturn( $now );
297 $mockDB1->method(
'getMasterPos' )->willReturn( $m1Pos );
300 ->disableOriginalConstructor()
302 $lb1->method(
'getConnection' )->willReturn( $mockDB1 );
303 $lb1->method(
'getServerCount' )->willReturn( 2 );
304 $lb1->method(
'getAnyOpenConnection' )->willReturn( $mockDB1 );
305 $lb1->method(
'hasOrMadeRecentMasterChanges' )->will( $this->returnCallback(
306 function ()
use ( $mockDB1 ) {
308 $p |= call_user_func( [ $mockDB1,
'writesOrCallbacksPending' ] );
309 $p |= call_user_func( [ $mockDB1,
'lastDoneWrites' ] );
314 $lb1->method(
'getMasterPos' )->willReturn( $m1Pos );
315 $lb1->method(
'getServerName' )->with( 0 )->willReturn(
'master1' );
318 ->disableOriginalConstructor()
320 $mockDB2->method(
'writesOrCallbacksPending' )->willReturn(
true );
321 $mockDB2->method(
'lastDoneWrites' )->willReturn( $now );
322 $mockDB2->method(
'getMasterPos' )->willReturn( $m2Pos );
325 ->disableOriginalConstructor()
327 $lb2->method(
'getConnection' )->willReturn( $mockDB2 );
328 $lb2->method(
'getServerCount' )->willReturn( 2 );
329 $lb2->method(
'getAnyOpenConnection' )->willReturn( $mockDB2 );
330 $lb2->method(
'hasOrMadeRecentMasterChanges' )->will( $this->returnCallback(
331 function ()
use ( $mockDB2 ) {
333 $p |= call_user_func( [ $mockDB2,
'writesOrCallbacksPending' ] );
334 $p |= call_user_func( [ $mockDB2,
'lastDoneWrites' ] );
339 $lb2->method(
'getMasterPos' )->willReturn( $m2Pos );
340 $lb2->method(
'getServerName' )->with( 0 )->willReturn(
'master2' );
347 'agent' =>
"Totally-Not-FireFox"
351 $mockDB1->expects( $this->exactly( 1 ) )->method(
'writesOrCallbacksPending' );
352 $mockDB1->expects( $this->exactly( 1 ) )->method(
'lastDoneWrites' );
353 $mockDB2->expects( $this->exactly( 1 ) )->method(
'writesOrCallbacksPending' );
354 $mockDB2->expects( $this->exactly( 1 ) )->method(
'lastDoneWrites' );
360 $cp->shutdownLB( $lb1 );
361 $cp->shutdownLB( $lb2 );
363 $cp->shutdown(
null,
'sync', $cpIndex );
365 $this->assertEquals( 1, $cpIndex,
"CP write index set" );
371 ->disableOriginalConstructor()
373 $lb1->method(
'getServerCount' )->willReturn( 2 );
374 $lb1->method(
'getServerName' )->with( 0 )->willReturn(
'master1' );
375 $lb1->expects( $this->once() )
376 ->method(
'waitFor' )->with( $this->equalTo( $m1Pos ) );
379 ->disableOriginalConstructor()
381 $lb2->method(
'getServerCount' )->willReturn( 2 );
382 $lb2->method(
'getServerName' )->with( 0 )->willReturn(
'master2' );
383 $lb2->expects( $this->once() )
384 ->method(
'waitFor' )->with( $this->equalTo( $m2Pos ) );
390 'agent' =>
"Totally-Not-FireFox"
399 $cp->shutdownLB( $lb1 );
400 $cp->shutdownLB( $lb2 );
402 $cp->shutdown(
null,
'sync', $cpIndex );
404 $this->assertEquals(
null, $cpIndex,
"CP write index retained" );
406 $this->assertEquals(
'45e93a9c215c031d38b7c42d8e4700ca', $cp->getClientId() );
414 'sectionsByDB' => [],
420 'serverTemplate' => $serverOverride + [
434 'agent' =>
'MW-UNIT-TESTS'
442 self::markTestSkipped(
"Skipping tests about selecting DBs: not applicable" );
450 $lb = $factory->getMainLB();
465 'Null domain ID handle used'
470 'Null domain ID handle used'
475 'Main domain ID handle used; prefix is empty though'
479 $db->tableName(
'page' ),
480 "Correct full table name"
484 $db->tableName(
"$wgDBname.page" ),
485 "Correct full table name"
489 $db->tableName(
'nice_db.page' ),
490 "Correct full table name"
493 $lb->reuseConnection(
$db );
496 $factory->setDomainPrefix(
'my_' );
505 $db->tableName(
'page' ),
506 "Correct full table name"
510 $db->tableName(
'other_nice_db.page' ),
511 "Correct full table name"
514 $factory->closeAll();
522 self::markTestSkipped(
"Skipping tests about selecting DBs: not applicable" );
526 $dbname =
'unittest-domain';
528 [
'localDomain' => (
new DatabaseDomain( $dbname,
null,
'' ) )->getId() ],
530 'dbName' =>
'do_not_select_me'
533 $lb = $factory->getMainLB();
537 $this->assertEquals(
'',
$db->getDomainID(),
"Null domain used" );
541 $db->tableName(
'page' ),
542 "Correct full table name"
547 $db->tableName(
"$dbname.page" ),
548 "Correct full table name"
553 $db->tableName(
'nice_db.page' ),
554 "Correct full table name"
557 $lb->reuseConnection(
$db );
559 $factory->setDomainPrefix(
'my_' );
560 $db = $lb->getConnection(
DB_MASTER, [],
"$wgDBname-my_" );
564 $db->tableName(
'page' ),
565 "Correct full table name"
569 $db->tableName(
'other_nice_db.page' ),
570 "Correct full table name"
574 $db->tableName(
'garbage-db.page' ),
575 "Correct full table name"
578 $lb->reuseConnection(
$db );
580 $factory->closeAll();
587 $dbname =
'unittest-domain';
589 [
'localDomain' => (
new DatabaseDomain( $dbname,
null,
'' ) )->getId() ],
591 'dbName' =>
'do_not_select_me'
594 $lb = $factory->getMainLB();
598 if (
$db->getType() ===
'sqlite' ) {
599 $this->assertFalse(
$db->selectDB(
'garbage-db' ) );
600 } elseif (
$db->databasesAreIndependent() ) {
603 $db->selectDB(
'garbage-db' );
604 }
catch ( \
Wikimedia\Rdbms\DBConnectionError
$e ) {
608 $this->assertFalse(
$db->isOpen() );
610 \Wikimedia\suppressWarnings();
612 $this->assertFalse(
$db->selectDB(
'garbage-db' ) );
613 $this->fail(
"No error thrown." );
616 "Could not select database 'garbage-db'.",
620 \Wikimedia\restoreWarnings();
628 self::markTestSkipped(
"Skipping tests about selecting DBs: not applicable" );
636 $lb = $factory->getMainLB();
638 $conn1 = $lb->getConnectionRef(
DB_MASTER );
641 $conn1->getDomainID()
645 $factory->redefineLocalDomain(
'somedb-prefix' );
646 $this->assertEquals(
'somedb-prefix', $factory->getLocalDomainID() );
649 $factory->redefineLocalDomain( $domain );
652 $lb->forEachOpenConnection(
function ()
use ( &$n ) {
655 $this->assertEquals( 0, $n,
"Connections closed" );
657 $conn2 = $lb->getConnectionRef(
DB_MASTER );
660 $conn2->getDomainID()
664 $factory->closeAll();
669 if (
$db->getType() ===
'sqlite' ) {
672 return $db->addIdentifierQuotes( $table );
682 $agentId = md5(
'Ramsey\'s Loyal Presa Canario' );
685 '3@542#c47dcfb0566e7d7bc110a6128a45c93a',
686 LBFactory::makeCookieValueFromCPIndex( 3, 542, $agentId )
690 $lbFactory->setRequestInfo( [
'IPAddress' =>
'10.64.24.52',
'UserAgent' =>
'meow' ] );
692 '1@542#c47dcfb0566e7d7bc110a6128a45c93a',
693 LBFactory::makeCookieValueFromCPIndex( 1, 542, $agentId )
698 LBFactory::getCPInfoFromCookieValue(
"5#$agentId",
$time - 10 )[
'index'],
703 LBFactory::getCPInfoFromCookieValue(
"5@$time",
$time - 10 )[
'index'],
708 LBFactory::getCPInfoFromCookieValue(
"0@$time#$agentId",
$time - 10 )[
'index'],
714 LBFactory::getCPInfoFromCookieValue(
"2@$time#$agentId",
$time - 10 )[
'index'],
719 LBFactory::getCPInfoFromCookieValue(
"2@$time#$agentId",
$time + 9 - 10 )[
'index'],
724 LBFactory::getCPInfoFromCookieValue(
"0@$time#$agentId",
$time + 9 - 10 )[
'index'],
725 'Almost stale; bad index'
729 LBFactory::getCPInfoFromCookieValue(
"2@$time#$agentId",
$time + 11 - 10 )[
'index'],
735 LBFactory::getCPInfoFromCookieValue(
"5@$time#$agentId",
$time - 10 )[
'clientId'],
740 LBFactory::getCPInfoFromCookieValue(
"5@$time#$agentId",
$time + 11 - 10 )[
'clientId'],