From 9225d40c0b7147cd6e166b998eecebbc07022d6a Mon Sep 17 00:00:00 2001 From: daniel Date: Mon, 4 Mar 2019 23:01:38 +0100 Subject: [PATCH] Make copyTestData work on postgres The issue with SQLite mentioned in the ticket remains unresolved for now. To make this less confusing, copyTestData() will throw for sqlite with an explanation instead of failing later. The test for copyTestData is skipped on sqlite as well. Bug: T217607 Change-Id: Ib9baa15cb6feff6c06959359f846b94ae6efab07 --- tests/phpunit/MediaWikiTestCase.php | 51 ++++++++++++------- tests/phpunit/tests/MediaWikiTestCaseTest.php | 35 +++++++++++++ 2 files changed, 69 insertions(+), 17 deletions(-) diff --git a/tests/phpunit/MediaWikiTestCase.php b/tests/phpunit/MediaWikiTestCase.php index 35f396ef78..36d66fb2aa 100644 --- a/tests/phpunit/MediaWikiTestCase.php +++ b/tests/phpunit/MediaWikiTestCase.php @@ -1595,7 +1595,7 @@ abstract class MediaWikiTestCase extends PHPUnit\Framework\TestCase { $this->ensureMockDatabaseConnection( $db ); $oldOverrides = $oldOverrides + self::$schemaOverrideDefaults; - $originalTables = $this->listOriginalTables( $db, 'unprefixed' ); + $originalTables = $this->listOriginalTables( $db ); // Drop tables that need to be restored or removed. $tablesToDrop = array_merge( $oldOverrides['create'], $oldOverrides['alter'] ); @@ -1656,7 +1656,7 @@ abstract class MediaWikiTestCase extends PHPUnit\Framework\TestCase { $this->ensureMockDatabaseConnection( $db ); // Drop the tables that will be created by the schema scripts. - $originalTables = $this->listOriginalTables( $db, 'unprefixed' ); + $originalTables = $this->listOriginalTables( $db ); $tablesToDrop = array_intersect( $originalTables, $overrides['create'] ); if ( $tablesToDrop ) { @@ -1701,29 +1701,36 @@ abstract class MediaWikiTestCase extends PHPUnit\Framework\TestCase { } /** - * Lists all tables in the live database schema. + * Lists all tables in the live database schema, without a prefix. * * @param IMaintainableDatabase $db - * @param string $prefix Either 'prefixed' or 'unprefixed' * @return array */ - private function listOriginalTables( IMaintainableDatabase $db, $prefix = 'prefixed' ) { + private function listOriginalTables( IMaintainableDatabase $db ) { if ( !isset( $db->_originalTablePrefix ) ) { throw new LogicException( 'No original table prefix know, cannot list tables!' ); } $originalTables = $db->listTables( $db->_originalTablePrefix, __METHOD__ ); - if ( $prefix === 'unprefixed' ) { - $originalPrefixRegex = '/^' . preg_quote( $db->_originalTablePrefix, '/' ) . '/'; - $originalTables = array_map( - function ( $pt ) use ( $originalPrefixRegex ) { - return preg_replace( $originalPrefixRegex, '', $pt ); - }, - $originalTables - ); - } - return $originalTables; + $unittestPrefixRegex = '/^' . preg_quote( $this->dbPrefix(), '/' ) . '/'; + $originalPrefixRegex = '/^' . preg_quote( $db->_originalTablePrefix, '/' ) . '/'; + + $originalTables = array_filter( + $originalTables, + function ( $pt ) use ( $unittestPrefixRegex ) { + return !preg_match( $unittestPrefixRegex, $pt ); + } + ); + + $originalTables = array_map( + function ( $pt ) use ( $originalPrefixRegex ) { + return preg_replace( $originalPrefixRegex, '', $pt ); + }, + $originalTables + ); + + return array_unique( $originalTables ); } /** @@ -1741,7 +1748,7 @@ abstract class MediaWikiTestCase extends PHPUnit\Framework\TestCase { throw new LogicException( 'No original table prefix know, cannot restore tables!' ); } - $originalTables = $this->listOriginalTables( $db, 'unprefixed' ); + $originalTables = $this->listOriginalTables( $db ); $tables = array_intersect( $tables, $originalTables ); $dbClone = new CloneDatabase( $db, $tables, $db->tablePrefix(), $db->_originalTablePrefix ); @@ -1889,7 +1896,17 @@ abstract class MediaWikiTestCase extends PHPUnit\Framework\TestCase { * @param IDatabase $target */ public function copyTestData( IDatabase $source, IDatabase $target ) { - $tables = self::listOriginalTables( $source, 'unprefixed' ); + if ( $this->db->getType() === 'sqlite' ) { + // SQLite uses a non-temporary copy of the searchindex table for testing, + // which gets deleted and re-created when setting up the secondary connection, + // causing "Error 17" when trying to copy the data. See T191863#4130112. + throw new RuntimeException( + 'Setting up a secondary database connection with test data is currently not' + . 'with SQLite. You may want to use markTestSkippedIfDbType() to bypass this issue.' + ); + } + + $tables = self::listOriginalTables( $source ); foreach ( $tables as $table ) { $res = $source->select( $table, '*', [], __METHOD__ ); diff --git a/tests/phpunit/tests/MediaWikiTestCaseTest.php b/tests/phpunit/tests/MediaWikiTestCaseTest.php index 599b733e05..6b5a487634 100644 --- a/tests/phpunit/tests/MediaWikiTestCaseTest.php +++ b/tests/phpunit/tests/MediaWikiTestCaseTest.php @@ -7,6 +7,7 @@ use Wikimedia\Rdbms\LoadBalancer; /** * @covers MediaWikiTestCase * @group MediaWikiTestCaseTest + * @group Database * * @author Addshore */ @@ -173,4 +174,38 @@ class MediaWikiTestCaseTest extends MediaWikiTestCase { $this->assertSame( $logger1, $logger2 ); } + + /** + * @covers MediaWikiTestCase::setupDatabaseWithTestPrefix + * @covers MediaWikiTestCase::copyTestData + */ + public function testCopyTestData() { + $this->markTestSkippedIfDbType( 'sqlite' ); + + $this->tablesUsed[] = 'objectcache'; + $this->db->insert( + 'objectcache', + [ 'keyname' => __METHOD__, 'value' => 'TEST', 'exptime' => $this->db->timestamp( 11 ) ], + __METHOD__ + ); + + $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory(); + $lb = $lbFactory->newMainLB(); + $db = $lb->getConnection( DB_REPLICA, DBO_TRX ); + + // sanity + $this->assertNotSame( $this->db, $db ); + + // Make sure the DB connection has the fake table clones and the fake table prefix + MediaWikiTestCase::setupDatabaseWithTestPrefix( $db, $this->dbPrefix(), false ); + + $this->assertSame( $this->db->tablePrefix(), $db->tablePrefix(), 'tablePrefix' ); + + // Make sure the DB connection has all the test data + $this->copyTestData( $this->db, $db ); + + $value = $db->selectField( 'objectcache', 'value', [ 'keyname' => __METHOD__ ], __METHOD__ ); + $this->assertSame( 'TEST', $value, 'Copied Data' ); + } + } -- 2.20.1