global $wgDBserver, $wgDBname, $wgDBuser, $wgDBpassword, $wgDBtype, $wgSQLiteDataDir;
$factory = new LBFactoryMulti( [
- 'sectionsByDB' => [],
+ 'sectionsByDB' => [
+ 's1wiki' => 's1',
+ ],
'sectionLoads' => [
+ 's1' => [
+ 'test-db3' => 0,
+ 'test-db4' => 100,
+ ],
'DEFAULT' => [
'test-db1' => 0,
'test-db2' => 100,
- ],
+ ]
],
'serverTemplate' => [
'dbname' => $wgDBname,
],
'hostsByName' => [
'test-db1' => $wgDBserver,
- 'test-db2' => $wgDBserver
+ 'test-db2' => $wgDBserver,
+ 'test-db3' => $wgDBserver,
+ 'test-db4' => $wgDBserver
],
'loadMonitorClass' => LoadMonitorNull::class
] );
$dbr = $lb->getConnection( DB_REPLICA );
$this->assertTrue( $dbr->getLBInfo( 'replica' ), 'slave shows as slave' );
+ // Test that LoadBalancer instances made during commitMasterChanges() do not throw
+ // DBTransactionError due to transaction ROUND_* stages being mismatched.
+ $factory->beginMasterChanges( __METHOD__ );
+ $dbw->onTransactionPreCommitOrIdle( function () use ( $factory ) {
+ // Trigger s1 LoadBalancer instantiation during "finalize" stage.
+ // There is no s1wiki DB to select so it is not in getConnection(),
+ // but this fools getMainLB() at least.
+ $factory->getMainLB( 's1wiki' )->getConnection( DB_MASTER );
+ } );
+ $factory->commitMasterChanges( __METHOD__ );
+
+ $count = 0;
+ $factory->forEachLB( function () use ( &$count ) {
+ ++$count;
+ } );
+ $this->assertEquals( 2, $count );
+
+ // DBTransactionError should not be thrown
+ $ran = 0;
+ $dbw->onTransactionPreCommitOrIdle( function () use ( &$ran ) {
+ ++$ran;
+ } );
+ $factory->commitAll( __METHOD__ );
+ $this->assertEquals( 1, $ran );
+
$factory->shutdown();
- $lb->closeAll();
+ $factory->closeAll();
}
/**
* @covers \Wikimedia\Rdbms\ChronologyProtector
*/
public function testChronologyProtector() {
- // (a) First HTTP request
- $m1Pos = new MySQLMasterPos( 'db1034-bin.000976', '843431247' );
- $m2Pos = new MySQLMasterPos( 'db1064-bin.002400', '794074907' );
-
$now = microtime( true );
+ // (a) First HTTP request
+ $m1Pos = new MySQLMasterPos( 'db1034-bin.000976/843431247', $now );
+ $m2Pos = new MySQLMasterPos( 'db1064-bin.002400/794074907', $now );
+
// Master DB 1
$mockDB1 = $this->getMockBuilder( DatabaseMysqli::class )
->disableOriginalConstructor()
}
public function testNiceDomains() {
- global $wgDBname, $wgDBtype;
-
- if ( $wgDBtype === 'sqlite' ) {
- $tmpDir = $this->getNewTempDirectory();
- $dbPath = "$tmpDir/unit_test_db.sqlite";
- file_put_contents( $dbPath, '' );
- $tempFsFile = new TempFSFile( $dbPath );
- $tempFsFile->autocollect();
- } else {
- $dbPath = null;
+ global $wgDBname;
+
+ if ( wfGetDB( DB_MASTER )->databasesAreIndependent() ) {
+ self::markTestSkipped( "Skipping tests about selecting DBs: not applicable" );
+ return;
}
$factory = $this->newLBFactoryMulti(
[],
- [ 'dbFilePath' => $dbPath ]
+ []
);
$lb = $factory->getMainLB();
- if ( $wgDBtype !== 'sqlite' ) {
- $db = $lb->getConnectionRef( DB_MASTER );
- $this->assertEquals(
- wfWikiID(),
- $db->getDomainID()
- );
- unset( $db );
- }
+ $db = $lb->getConnectionRef( DB_MASTER );
+ $this->assertEquals(
+ wfWikiID(),
+ $db->getDomainID()
+ );
+ unset( $db );
/** @var Database $db */
$db = $lb->getConnection( DB_MASTER, [], '' );
$db = $lb->getConnection( DB_MASTER ); // local domain connection
$factory->setDomainPrefix( 'my_' );
+ $this->assertEquals( $wgDBname, $db->getDBname() );
$this->assertEquals(
"$wgDBname-my_",
$db->getDomainID()
}
public function testTrickyDomain() {
- global $wgDBtype, $wgDBname;
-
- if ( $wgDBtype === 'sqlite' ) {
- $tmpDir = $this->getNewTempDirectory();
- $dbPath = "$tmpDir/unit_test_db.sqlite";
- file_put_contents( $dbPath, '' );
- $tempFsFile = new TempFSFile( $dbPath );
- $tempFsFile->autocollect();
- } else {
- $dbPath = null;
+ global $wgDBname;
+
+ if ( wfGetDB( DB_MASTER )->databasesAreIndependent() ) {
+ self::markTestSkipped( "Skipping tests about selecting DBs: not applicable" );
+ return;
}
$dbname = 'unittest-domain'; // explodes if DB is selected
$factory = $this->newLBFactoryMulti(
[ 'localDomain' => ( new DatabaseDomain( $dbname, null, '' ) )->getId() ],
[
- 'dbFilePath' => $dbPath,
'dbName' => 'do_not_select_me' // explodes if DB is selected
]
);
"Correct full table name"
);
- if ( $db->databasesAreIndependent() ) {
+ $lb->reuseConnection( $db ); // don't care
+
+ $factory->closeAll();
+ $factory->destroy();
+ }
+
+ public function testInvalidSelectDB() {
+ $dbname = 'unittest-domain'; // explodes if DB is selected
+ $factory = $this->newLBFactoryMulti(
+ [ 'localDomain' => ( new DatabaseDomain( $dbname, null, '' ) )->getId() ],
+ [
+ 'dbName' => 'do_not_select_me' // explodes if DB is selected
+ ]
+ );
+ $lb = $factory->getMainLB();
+ /** @var Database $db */
+ $db = $lb->getConnection( DB_MASTER, [], '' );
+
+ if ( $db->getType() === 'sqlite' ) {
+ $this->assertFalse( $db->selectDB( 'garbage-db' ) );
+ } elseif ( $db->databasesAreIndependent() ) {
try {
$e = null;
$db->selectDB( 'garbage-db' );
$this->assertInstanceOf( \Wikimedia\Rdbms\DBConnectionError::class, $e );
$this->assertFalse( $db->isOpen() );
} else {
- \MediaWiki\suppressWarnings();
+ \Wikimedia\suppressWarnings();
$this->assertFalse( $db->selectDB( 'garbage-db' ) );
- \MediaWiki\restoreWarnings();
+ \Wikimedia\restoreWarnings();
}
-
- $lb->reuseConnection( $db ); // don't care
-
- $factory->closeAll();
- $factory->destroy();
}
private function quoteTable( Database $db, $table ) {