rdbms: enforce and improve LBFactory/LoadBalancer callback handling
[lhc/web/wiklou.git] / tests / phpunit / includes / libs / rdbms / database / DatabaseTest.php
index 3335a2b..f08b376 100644 (file)
@@ -9,6 +9,7 @@ use Wikimedia\TestingAccessWrapper;
 use Wikimedia\Rdbms\DatabaseSqlite;
 use Wikimedia\Rdbms\DatabasePostgres;
 use Wikimedia\Rdbms\DatabaseMssql;
+use Wikimedia\Rdbms\DBUnexpectedError;
 
 class DatabaseTest extends PHPUnit\Framework\TestCase {
 
@@ -367,7 +368,7 @@ class DatabaseTest extends PHPUnit\Framework\TestCase {
                        $called = true;
                        $db->setFlag( DBO_TRX );
                } );
-               $db->rollback( __METHOD__, IDatabase::FLUSHING_ALL_PEERS );
+               $db->rollback( __METHOD__ );
                $this->assertFalse( $db->getFlag( DBO_TRX ), 'DBO_TRX restored to default' );
                $this->assertTrue( $called, 'Callback reached' );
        }
@@ -489,37 +490,56 @@ class DatabaseTest extends PHPUnit\Framework\TestCase {
                $this->assertEquals( true, $db->lockIsFree( 'x', __METHOD__ ) );
                $db->clearFlag( DBO_TRX );
 
+               // Pending writes with DBO_TRX
                $this->assertEquals( 0, $db->trxLevel() );
-
+               $this->assertTrue( $db->lockIsFree( 'meow', __METHOD__ ) );
                $db->setFlag( DBO_TRX );
+               $db->query( "DELETE FROM test WHERE t = 1" ); // trigger DBO_TRX transaction before lock
                try {
-                       $this->badLockingMethodImplicit( $db );
-               } catch ( RunTimeException $e ) {
-                       $this->assertTrue( $db->trxLevel() > 0, "Transaction not committed." );
+                       $lock = $db->getScopedLockAndFlush( 'meow', __METHOD__, 1 );
+                       $this->fail( "Exception not reached" );
+               } catch ( DBUnexpectedError $e ) {
+                       $this->assertEquals( 1, $db->trxLevel(), "Transaction not committed." );
+                       $this->assertTrue( $db->lockIsFree( 'meow', __METHOD__ ), 'Lock not acquired' );
                }
-               $db->clearFlag( DBO_TRX );
                $db->rollback( __METHOD__, IDatabase::FLUSHING_ALL_PEERS );
-               $this->assertTrue( $db->lockIsFree( 'meow', __METHOD__ ) );
-
+               // Pending writes without DBO_TRX
+               $db->clearFlag( DBO_TRX );
+               $this->assertEquals( 0, $db->trxLevel() );
+               $this->assertTrue( $db->lockIsFree( 'meow2', __METHOD__ ) );
+               $db->begin( __METHOD__ );
+               $db->query( "DELETE FROM test WHERE t = 1" ); // trigger DBO_TRX transaction before lock
                try {
-                       $this->badLockingMethodExplicit( $db );
-               } catch ( RunTimeException $e ) {
-                       $this->assertTrue( $db->trxLevel() > 0, "Transaction not committed." );
+                       $lock = $db->getScopedLockAndFlush( 'meow2', __METHOD__, 1 );
+                       $this->fail( "Exception not reached" );
+               } catch ( DBUnexpectedError $e ) {
+                       $this->assertEquals( 1, $db->trxLevel(), "Transaction not committed." );
+                       $this->assertTrue( $db->lockIsFree( 'meow2', __METHOD__ ), 'Lock not acquired' );
                }
+               $db->rollback( __METHOD__ );
+               // No pending writes, with DBO_TRX
+               $db->setFlag( DBO_TRX );
+               $this->assertEquals( 0, $db->trxLevel() );
+               $this->assertTrue( $db->lockIsFree( 'wuff', __METHOD__ ) );
+               $db->query( "SELECT 1", __METHOD__ );
+               $this->assertEquals( 1, $db->trxLevel() );
+               $lock = $db->getScopedLockAndFlush( 'wuff', __METHOD__, 1 );
+               $this->assertEquals( 0, $db->trxLevel() );
+               $this->assertFalse( $db->lockIsFree( 'wuff', __METHOD__ ), 'Lock already acquired' );
                $db->rollback( __METHOD__, IDatabase::FLUSHING_ALL_PEERS );
-               $this->assertTrue( $db->lockIsFree( 'meow', __METHOD__ ) );
-       }
-
-       private function badLockingMethodImplicit( IDatabase $db ) {
-               $lock = $db->getScopedLockAndFlush( 'meow', __METHOD__, 1 );
-               $db->query( "SELECT 1" ); // trigger DBO_TRX
-               throw new RunTimeException( "Uh oh!" );
-       }
-
-       private function badLockingMethodExplicit( IDatabase $db ) {
-               $lock = $db->getScopedLockAndFlush( 'meow', __METHOD__, 1 );
+               // No pending writes, without DBO_TRX
+               $db->clearFlag( DBO_TRX );
+               $this->assertEquals( 0, $db->trxLevel() );
+               $this->assertTrue( $db->lockIsFree( 'wuff2', __METHOD__ ) );
                $db->begin( __METHOD__ );
-               throw new RunTimeException( "Uh oh!" );
+               try {
+                       $lock = $db->getScopedLockAndFlush( 'wuff2', __METHOD__, 1 );
+                       $this->fail( "Exception not reached" );
+               } catch ( DBUnexpectedError $e ) {
+                       $this->assertEquals( 1, $db->trxLevel(), "Transaction not committed." );
+                       $this->assertFalse( $db->lockIsFree( 'wuff2', __METHOD__ ), 'Lock not acquired' );
+               }
+               $db->rollback( __METHOD__ );
        }
 
        /**