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" ],
82 "`\u{0001}a\u{FFFF}b`",
87 "\u{0001}\u{0000}\u{FFFF}\u{0000}"
90 [
'`メインページ`',
'メインページ' ],
91 [
'`Басты_бет`',
'Басты_бет' ],
94 [
'`Alix`',
'Alix' ], #
while( ! $recovered ) { sleep(); }
95 [
'`Backtick: ```',
'Backtick: `' ],
96 [
'`This is a test`',
'This is a test' ],
102 ->disableOriginalConstructor()
103 ->setMethods( [
'fetchRow',
'query',
'getDBname' ] )
106 $db->method(
'query' )
108 ->willReturn(
new FakeResultWrapper( [
109 (
object)[
'Tables_in_' =>
'view1' ],
110 (
object)[
'Tables_in_' =>
'view2' ],
111 (
object)[
'Tables_in_' =>
'myview' ]
113 $db->method(
'getDBname' )->willReturn(
'' );
124 $this->assertEquals( [
'view1',
'view2',
'myview' ],
128 $this->assertEquals( [
'view1',
'view2' ],
129 $db->listViews(
'view' ) );
130 $this->assertEquals( [
'myview' ],
131 $db->listViews(
'my' ) );
132 $this->assertEquals( [],
133 $db->listViews(
'UNUSED_PREFIX' ) );
134 $this->assertEquals( [
'view1',
'view2',
'myview' ],
135 $db->listViews(
'' ) );
144 $this->assertEquals(
"db1052", $pos->getLogName() );
145 $this->assertEquals(
"db1052.2424", $pos->getLogFile() );
146 $this->assertEquals( [ 2424, 4643 ], $pos->getLogPosition() );
161 $this->assertFalse( $higherPos->
hasReached( $lowerPos ) );
163 $this->assertTrue( $higherPos->
hasReached( $lowerPos ) );
165 $this->assertTrue( $lowerPos->
hasReached( $lowerPos ) );
166 $this->assertTrue( $higherPos->
hasReached( $higherPos ) );
167 $this->assertFalse( $lowerPos->
hasReached( $higherPos ) );
169 $this->assertFalse( $lowerPos->
channelsMatch( $higherPos ) );
171 $this->assertFalse( $higherPos->
hasReached( $lowerPos ) );
172 $this->assertFalse( $lowerPos->
hasReached( $higherPos ) );
177 $now = microtime(
true );
201 new MySQLMasterPos(
'3E11FA47-71CA-11E1-9E33-C80AA9429562:1-23', $now ),
202 new MySQLMasterPos(
'3E11FA47-71CA-11E1-9E33-C80AA9429562:5-24', $now ),
207 new MySQLMasterPos(
'3E11FA47-71CA-11E1-9E33-C80AA9429562:5-99', $now ),
208 new MySQLMasterPos(
'3E11FA47-71CA-11E1-9E33-C80AA9429562:1-100', $now ),
213 new MySQLMasterPos(
'3E11FA47-71CA-11E1-9E33-C80AA9429562:1-99', $now ),
214 new MySQLMasterPos(
'1E11FA47-71CA-11E1-9E33-C80AA9429562:1-100', $now ),
285 $this->assertEquals( (
string)$pos1, (
string)$roundtripPos );
289 $now = microtime(
true );
320 $this->assertEquals( $gtids, MySQLMasterPos::getCommonDomainGTIDs( $pos, $ref ) );
332 '2E11FA47-71CA-11E1-9E33-C80AA9429562:1-5,' .
333 '3E11FA47-71CA-11E1-9E33-C80AA9429562:20-99,' .
334 '7E11FA47-71CA-11E1-9E33-C80AA9429562:1-30',
338 '1E11FA47-71CA-11E1-9E33-C80AA9429562:30-100,' .
339 '3E11FA47-71CA-11E1-9E33-C80AA9429562:30-66',
342 [
'3E11FA47-71CA-11E1-9E33-C80AA9429562:20-99' ]
354 ->disableOriginalConstructor()
356 'getLagDetectionMethod',
'getHeartbeatData',
'getMasterServerInfo' ] )
359 $db->method(
'getLagDetectionMethod' )
360 ->willReturn(
'pt-heartbeat' );
362 $db->method(
'getMasterServerInfo' )
363 ->willReturn( [
'serverId' => 172,
'asOf' => time() ] );
366 list( $nowSecFrac, $nowSec ) = explode(
' ', microtime() );
367 $now = (float)$nowSec + (
float)$nowSecFrac;
370 $ptTime = $now - $lag;
371 $ptSec = (int)$ptTime;
372 $ptSecFrac = ( $ptTime - $ptSec );
373 $ptDateTime =
new DateTime(
"@$ptSec" );
374 $ptTimeISO = $ptDateTime->format(
'Y-m-d\TH:i:s' );
375 $ptTimeISO .= ltrim( number_format( $ptSecFrac, 6 ),
'0' );
377 $db->method(
'getHeartbeatData' )
378 ->with( [
'server_id' => 172 ] )
379 ->willReturn( [ $ptTimeISO, $now ] );
381 $db->setLBInfo(
'clusterMasterHost',
'db1052' );
382 $lagEst = $db->getLag();
384 $this->assertGreaterThan( $lag - 0.010, $lagEst,
"Correct heatbeat lag" );
385 $this->assertLessThan( $lag + 0.010, $lagEst,
"Correct heatbeat lag" );
409 ->disableOriginalConstructor()
413 'getServerRoleStatus',
419 $db->method(
'useGTIDs' )->willReturn(
true );
420 $db->method(
'getServerGTIDs' )->willReturn( $gtable );
421 $db->method(
'getServerRoleStatus' )->willReturnCallback(
422 function ( $role )
use ( $rBLtable, $mBLtable ) {
423 if ( $role ===
'SLAVE' ) {
425 } elseif ( $role ===
'MASTER' ) {
432 $db->method(
'getServerId' )->willReturn( 1 );
433 $db->method(
'getServerUUID' )->willReturn(
'2E11FA47-71CA-11E1-9E33-C80AA9429562' );
435 if ( is_array( $rGTIDs ) ) {
436 $this->assertEquals( $rGTIDs, $db->getReplicaPos()->getGTIDs() );
438 $this->assertEquals(
false, $db->getReplicaPos() );
440 if ( is_array( $mGTIDs ) ) {
441 $this->assertEquals( $mGTIDs, $db->getMasterPos()->getGTIDs() );
443 $this->assertEquals(
false, $db->getMasterPos() );
452 'gtid_domain_id' => 100,
453 'gtid_current_pos' =>
'100-13-77',
454 'gtid_binlog_pos' =>
'100-13-77',
455 'gtid_slave_pos' =>
null
458 'Relay_Master_Log_File' =>
'host.1600',
459 'Exec_Master_Log_Pos' =>
'77'
462 'File' =>
'host.1600',
466 [
'100' =>
'100-13-77' ]
470 'gtid_domain_id' => 100,
471 'gtid_current_pos' =>
'100-13-77',
472 'gtid_binlog_pos' =>
'100-13-77',
473 'gtid_slave_pos' =>
'100-13-77'
476 'Relay_Master_Log_File' =>
'host.1600',
477 'Exec_Master_Log_Pos' =>
'77'
480 [
'100' =>
'100-13-77' ],
481 [
'100' =>
'100-13-77' ]
485 'gtid_current_pos' =>
'100-13-77',
486 'gtid_binlog_pos' =>
'100-13-77',
487 'gtid_slave_pos' =>
'100-13-77'
490 'Relay_Master_Log_File' =>
'host.1600',
491 'Exec_Master_Log_Pos' =>
'77'
494 [
'100' =>
'100-13-77' ],
495 [
'100' =>
'100-13-77' ]
500 'gtid_executed' =>
'2E11FA47-71CA-11E1-9E33-C80AA9429562:1-77'
503 'Relay_Master_Log_File' =>
'host.1600',
504 'Exec_Master_Log_Pos' =>
'77'
507 [
'2E11FA47-71CA-11E1-9E33-C80AA9429562'
508 =>
'2E11FA47-71CA-11E1-9E33-C80AA9429562:1-77' ],
510 [
'2E11FA47-71CA-11E1-9E33-C80AA9429562'
511 =>
'2E11FA47-71CA-11E1-9E33-C80AA9429562:1-77' ],
515 'gtid_executed' =>
'2E11FA47-71CA-11E1-9E33-C80AA9429562:1-49,' .
516 '2E11FA47-71CA-11E1-9E33-C80AA9429562:51-77'
519 'Relay_Master_Log_File' =>
'host.1600',
520 'Exec_Master_Log_Pos' =>
'77'
523 [
'2E11FA47-71CA-11E1-9E33-C80AA9429562'
524 =>
'2E11FA47-71CA-11E1-9E33-C80AA9429562:51-77' ],
526 [
'2E11FA47-71CA-11E1-9E33-C80AA9429562'
527 =>
'2E11FA47-71CA-11E1-9E33-C80AA9429562:51-77' ],
531 'gtid_executed' =>
null,
532 'gtid_binlog_pos' => null
535 'Relay_Master_Log_File' =>
'host.1600',
536 'Exec_Master_Log_Pos' =>
'77'
544 'gtid_executed' =>
null,
545 'gtid_binlog_pos' => null
559 $pos =
new MySQLMasterPos(
'3E11FA47-71CA-11E1-9E33-C80AA9429562:99', 53636363 );
562 $this->assertEquals( $pos, $roundtripPos );
567 $this->assertEquals( $pos, $roundtripPos );
576 ->disableOriginalConstructor()
577 ->setMethods( [
'getReplicationSafetyInfo' ] )
579 $db->method(
'getReplicationSafetyInfo' )->willReturn( (
object)$row );
580 $dbw = TestingAccessWrapper::newFromObject( $db );
582 $this->assertEquals( $safe, $dbw->isInsertSelectSafe( $insertOpts, $selectOpts ) );
591 'innodb_autoinc_lock_mode' =>
'2',
592 'binlog_format' =>
'ROW',
600 'innodb_autoinc_lock_mode' =>
'2',
601 'binlog_format' =>
'ROW',
609 'innodb_autoinc_lock_mode' =>
'0',
610 'binlog_format' =>
'STATEMENT',
618 'innodb_autoinc_lock_mode' =>
'2',
619 'binlog_format' =>
'STATEMENT',
624 [
'NO_AUTO_COLUMNS' ],
627 'innodb_autoinc_lock_mode' =>
'0',
628 'binlog_format' =>
'STATEMENT',
636 'innodb_autoinc_lock_mode' => 0,
637 'binlog_format' =>
'STATEMENT',
642 [
'NO_AUTO_COLUMNS' ],
645 'innodb_autoinc_lock_mode' => 2,
646 'binlog_format' =>
'STATEMENT',
651 [
'NO_AUTO_COLUMNS' ],
654 'innodb_autoinc_lock_mode' => 0,
655 'binlog_format' =>
'STATEMENT',
668 ->disableOriginalConstructor()
671 $output = $db->buildIntegerCast(
'fieldName' );
672 $this->assertSame(
'CAST( fieldName AS SIGNED )',
$output );
680 ->disableOriginalConstructor()
681 ->setMethods( [
'mysqlRealEscapeString',
'dbSchema',
'tablePrefix' ] )
683 $db->method(
'mysqlRealEscapeString' )->willReturnCallback(
685 return str_replace(
"'",
"\\'",
$s );
689 $db->setIndexAliases( [
'a_b_idx' =>
'a_c_idx' ] );
690 $sql = $db->selectSQLText(
691 'zend',
'field', [
'a' =>
'x' ], __METHOD__, [
'USE INDEX' =>
'a_b_idx' ] );
694 "SELECT field FROM `zend` FORCE INDEX (a_c_idx) WHERE a = 'x' ",
698 $db->setIndexAliases( [] );
699 $sql = $db->selectSQLText(
700 'zend',
'field', [
'a' =>
'x' ], __METHOD__, [
'USE INDEX' =>
'a_b_idx' ] );
703 "SELECT field FROM `zend` FORCE INDEX (a_b_idx) WHERE a = 'x' ",
713 ->disableOriginalConstructor()
714 ->setMethods( [
'mysqlRealEscapeString',
'dbSchema',
'tablePrefix' ] )
716 $db->method(
'mysqlRealEscapeString' )->willReturnCallback(
718 return str_replace(
"'",
"\\'",
$s );
722 $db->setTableAliases( [
723 'meow' => [
'dbname' =>
'feline',
'schema' =>
null,
'prefix' =>
'cat_' ]
725 $sql = $db->selectSQLText(
'meow',
'field', [
'a' =>
'x' ], __METHOD__ );
728 "SELECT field FROM `feline`.`cat_meow` WHERE a = 'x' ",
732 $db->setTableAliases( [] );
733 $sql = $db->selectSQLText(
'meow',
'field', [
'a' =>
'x' ], __METHOD__ );
736 "SELECT field FROM `meow` WHERE a = 'x' ",