27 use Wikimedia\TestingAccessWrapper;
31 use MediaWikiCoversValidator;
32 use PHPUnit4And6Compat;
40 ->disableOriginalConstructor()
44 $quoted = $db->addIdentifierQuotes( $in );
45 $this->assertEquals( $expected, $quoted );
71 [
"`'`",
"'" ], # single quote
72 [
'`"`',
'"' ], #
double quote
73 [
'````',
'`' ], # backtick
74 [
'`’`',
'’' ], # apostrophe (look at your encyclopedia)
78 [
'`xyzzy`',
"\0x\0y\0z\0z\0y\0" ],
90 [
'`メインページ`',
'メインページ' ],
91 [
'`Басты_бет`',
'Басты_бет' ],
94 [
'`Alix`',
'Alix' ], #
while( ! $recovered ) { sleep(); }
95 [
'`Backtick: ```',
'Backtick: `' ],
96 [
'`This is a test`',
'This is a test' ],
101 return json_decode(
'"' . $str .
'"' );
106 ->disableOriginalConstructor()
107 ->setMethods( [
'fetchRow',
'query' ] )
110 $db->method(
'query' )
112 ->willReturn(
new FakeResultWrapper( [
113 (
object)[
'Tables_in_' =>
'view1' ],
114 (
object)[
'Tables_in_' =>
'view2' ],
115 (
object)[
'Tables_in_' =>
'myview' ]
127 $this->assertEquals( [
'view1',
'view2',
'myview' ],
131 $this->assertEquals( [
'view1',
'view2' ],
132 $db->listViews(
'view' ) );
133 $this->assertEquals( [
'myview' ],
134 $db->listViews(
'my' ) );
135 $this->assertEquals( [],
136 $db->listViews(
'UNUSED_PREFIX' ) );
137 $this->assertEquals( [
'view1',
'view2',
'myview' ],
138 $db->listViews(
'' ) );
147 $this->assertEquals(
"db1052", $pos->getLogName() );
148 $this->assertEquals(
"db1052.2424", $pos->getLogFile() );
149 $this->assertEquals( [ 2424, 4643 ], $pos->getLogPosition() );
164 $this->assertFalse( $higherPos->
hasReached( $lowerPos ) );
166 $this->assertTrue( $higherPos->
hasReached( $lowerPos ) );
168 $this->assertTrue( $lowerPos->
hasReached( $lowerPos ) );
169 $this->assertTrue( $higherPos->
hasReached( $higherPos ) );
170 $this->assertFalse( $lowerPos->
hasReached( $higherPos ) );
172 $this->assertFalse( $lowerPos->
channelsMatch( $higherPos ) );
174 $this->assertFalse( $higherPos->
hasReached( $lowerPos ) );
175 $this->assertFalse( $lowerPos->
hasReached( $higherPos ) );
180 $now = microtime(
true );
204 new MySQLMasterPos(
'3E11FA47-71CA-11E1-9E33-C80AA9429562:1-23', $now ),
205 new MySQLMasterPos(
'3E11FA47-71CA-11E1-9E33-C80AA9429562:5-24', $now ),
210 new MySQLMasterPos(
'3E11FA47-71CA-11E1-9E33-C80AA9429562:5-99', $now ),
211 new MySQLMasterPos(
'3E11FA47-71CA-11E1-9E33-C80AA9429562:1-100', $now ),
216 new MySQLMasterPos(
'3E11FA47-71CA-11E1-9E33-C80AA9429562:1-99', $now ),
217 new MySQLMasterPos(
'1E11FA47-71CA-11E1-9E33-C80AA9429562:1-100', $now ),
288 $this->assertEquals( (
string)$pos1, (
string)$roundtripPos );
292 $now = microtime(
true );
323 $this->assertEquals( $gtids, MySQLMasterPos::getCommonDomainGTIDs( $pos, $ref ) );
335 '2E11FA47-71CA-11E1-9E33-C80AA9429562:1-5,' .
336 '3E11FA47-71CA-11E1-9E33-C80AA9429562:20-99,' .
337 '7E11FA47-71CA-11E1-9E33-C80AA9429562:1-30',
341 '1E11FA47-71CA-11E1-9E33-C80AA9429562:30-100,' .
342 '3E11FA47-71CA-11E1-9E33-C80AA9429562:30-66',
345 [
'3E11FA47-71CA-11E1-9E33-C80AA9429562:20-99' ]
357 ->disableOriginalConstructor()
359 'getLagDetectionMethod',
'getHeartbeatData',
'getMasterServerInfo' ] )
362 $db->method(
'getLagDetectionMethod' )
363 ->willReturn(
'pt-heartbeat' );
365 $db->method(
'getMasterServerInfo' )
366 ->willReturn( [
'serverId' => 172,
'asOf' => time() ] );
369 list( $nowSecFrac, $nowSec ) = explode(
' ', microtime() );
370 $now = (float)$nowSec + (
float)$nowSecFrac;
373 $ptTime = $now - $lag;
374 $ptSec = (int)$ptTime;
375 $ptSecFrac = ( $ptTime - $ptSec );
376 $ptDateTime =
new DateTime(
"@$ptSec" );
377 $ptTimeISO = $ptDateTime->format(
'Y-m-d\TH:i:s' );
378 $ptTimeISO .= ltrim( number_format( $ptSecFrac, 6 ),
'0' );
380 $db->method(
'getHeartbeatData' )
381 ->with( [
'server_id' => 172 ] )
382 ->willReturn( [ $ptTimeISO, $now ] );
384 $db->setLBInfo(
'clusterMasterHost',
'db1052' );
385 $lagEst = $db->getLag();
387 $this->assertGreaterThan( $lag - 0.010, $lagEst,
"Correct heatbeat lag" );
388 $this->assertLessThan( $lag + 0.010, $lagEst,
"Correct heatbeat lag" );
412 ->disableOriginalConstructor()
416 'getServerRoleStatus',
422 $db->method(
'useGTIDs' )->willReturn(
true );
423 $db->method(
'getServerGTIDs' )->willReturn( $gtable );
424 $db->method(
'getServerRoleStatus' )->willReturnCallback(
425 function ( $role )
use ( $rBLtable, $mBLtable ) {
426 if ( $role ===
'SLAVE' ) {
428 } elseif ( $role ===
'MASTER' ) {
435 $db->method(
'getServerId' )->willReturn( 1 );
436 $db->method(
'getServerUUID' )->willReturn(
'2E11FA47-71CA-11E1-9E33-C80AA9429562' );
438 if ( is_array( $rGTIDs ) ) {
439 $this->assertEquals( $rGTIDs, $db->getReplicaPos()->getGTIDs() );
441 $this->assertEquals(
false, $db->getReplicaPos() );
443 if ( is_array( $mGTIDs ) ) {
444 $this->assertEquals( $mGTIDs, $db->getMasterPos()->getGTIDs() );
446 $this->assertEquals(
false, $db->getMasterPos() );
455 'gtid_domain_id' => 100,
456 'gtid_current_pos' =>
'100-13-77',
457 'gtid_binlog_pos' =>
'100-13-77',
458 'gtid_slave_pos' =>
null
461 'Relay_Master_Log_File' =>
'host.1600',
462 'Exec_Master_Log_Pos' =>
'77'
465 'File' =>
'host.1600',
469 [
'100' =>
'100-13-77' ]
473 'gtid_domain_id' => 100,
474 'gtid_current_pos' =>
'100-13-77',
475 'gtid_binlog_pos' =>
'100-13-77',
476 'gtid_slave_pos' =>
'100-13-77'
479 'Relay_Master_Log_File' =>
'host.1600',
480 'Exec_Master_Log_Pos' =>
'77'
483 [
'100' =>
'100-13-77' ],
484 [
'100' =>
'100-13-77' ]
488 'gtid_current_pos' =>
'100-13-77',
489 'gtid_binlog_pos' =>
'100-13-77',
490 'gtid_slave_pos' =>
'100-13-77'
493 'Relay_Master_Log_File' =>
'host.1600',
494 'Exec_Master_Log_Pos' =>
'77'
497 [
'100' =>
'100-13-77' ],
498 [
'100' =>
'100-13-77' ]
503 'gtid_executed' =>
'2E11FA47-71CA-11E1-9E33-C80AA9429562:1-77'
506 'Relay_Master_Log_File' =>
'host.1600',
507 'Exec_Master_Log_Pos' =>
'77'
510 [
'2E11FA47-71CA-11E1-9E33-C80AA9429562'
511 =>
'2E11FA47-71CA-11E1-9E33-C80AA9429562:1-77' ],
513 [
'2E11FA47-71CA-11E1-9E33-C80AA9429562'
514 =>
'2E11FA47-71CA-11E1-9E33-C80AA9429562:1-77' ],
518 'gtid_executed' =>
'2E11FA47-71CA-11E1-9E33-C80AA9429562:1-49,' .
519 '2E11FA47-71CA-11E1-9E33-C80AA9429562:51-77'
522 'Relay_Master_Log_File' =>
'host.1600',
523 'Exec_Master_Log_Pos' =>
'77'
526 [
'2E11FA47-71CA-11E1-9E33-C80AA9429562'
527 =>
'2E11FA47-71CA-11E1-9E33-C80AA9429562:51-77' ],
529 [
'2E11FA47-71CA-11E1-9E33-C80AA9429562'
530 =>
'2E11FA47-71CA-11E1-9E33-C80AA9429562:51-77' ],
534 'gtid_executed' =>
null,
535 'gtid_binlog_pos' => null
538 'Relay_Master_Log_File' =>
'host.1600',
539 'Exec_Master_Log_Pos' =>
'77'
547 'gtid_executed' =>
null,
548 'gtid_binlog_pos' => null
562 $pos =
new MySQLMasterPos(
'3E11FA47-71CA-11E1-9E33-C80AA9429562:99', 53636363 );
565 $this->assertEquals( $pos, $roundtripPos );
570 $this->assertEquals( $pos, $roundtripPos );
579 ->disableOriginalConstructor()
580 ->setMethods( [
'getReplicationSafetyInfo' ] )
582 $db->method(
'getReplicationSafetyInfo' )->willReturn( (
object)$row );
583 $dbw = TestingAccessWrapper::newFromObject( $db );
585 $this->assertEquals( $safe, $dbw->isInsertSelectSafe( $insertOpts, $selectOpts ) );
594 'innodb_autoinc_lock_mode' =>
'2',
595 'binlog_format' =>
'ROW',
603 'innodb_autoinc_lock_mode' =>
'2',
604 'binlog_format' =>
'ROW',
612 'innodb_autoinc_lock_mode' =>
'0',
613 'binlog_format' =>
'STATEMENT',
621 'innodb_autoinc_lock_mode' =>
'2',
622 'binlog_format' =>
'STATEMENT',
627 [
'NO_AUTO_COLUMNS' ],
630 'innodb_autoinc_lock_mode' =>
'0',
631 'binlog_format' =>
'STATEMENT',
639 'innodb_autoinc_lock_mode' => 0,
640 'binlog_format' =>
'STATEMENT',
645 [
'NO_AUTO_COLUMNS' ],
648 'innodb_autoinc_lock_mode' => 2,
649 'binlog_format' =>
'STATEMENT',
654 [
'NO_AUTO_COLUMNS' ],
657 'innodb_autoinc_lock_mode' => 0,
658 'binlog_format' =>
'STATEMENT',
671 ->disableOriginalConstructor()
674 $output = $db->buildIntegerCast(
'fieldName' );
675 $this->assertSame(
'CAST( fieldName AS SIGNED )',
$output );
683 ->disableOriginalConstructor()
684 ->setMethods( [
'mysqlRealEscapeString' ] )
686 $db->method(
'mysqlRealEscapeString' )->willReturnCallback(
688 return str_replace(
"'",
"\\'",
$s );
692 $db->setIndexAliases( [
'a_b_idx' =>
'a_c_idx' ] );
693 $sql = $db->selectSQLText(
694 'zend',
'field', [
'a' =>
'x' ], __METHOD__, [
'USE INDEX' =>
'a_b_idx' ] );
697 "SELECT field FROM `zend` FORCE INDEX (a_c_idx) WHERE a = 'x' ",
701 $db->setIndexAliases( [] );
702 $sql = $db->selectSQLText(
703 'zend',
'field', [
'a' =>
'x' ], __METHOD__, [
'USE INDEX' =>
'a_b_idx' ] );
706 "SELECT field FROM `zend` FORCE INDEX (a_b_idx) WHERE a = 'x' ",
716 ->disableOriginalConstructor()
717 ->setMethods( [
'mysqlRealEscapeString' ] )
719 $db->method(
'mysqlRealEscapeString' )->willReturnCallback(
721 return str_replace(
"'",
"\\'",
$s );
725 $db->setTableAliases( [
726 'meow' => [
'dbname' =>
'feline',
'schema' =>
null,
'prefix' =>
'cat_' ]
728 $sql = $db->selectSQLText(
'meow',
'field', [
'a' =>
'x' ], __METHOD__ );
731 "SELECT field FROM `feline`.`cat_meow` WHERE a = 'x' ",
735 $db->setTableAliases( [] );
736 $sql = $db->selectSQLText(
'meow',
'field', [
'a' =>
'x' ], __METHOD__ );
739 "SELECT field FROM `meow` WHERE a = 'x' ",