X-Git-Url: https://git.heureux-cyclage.org/?p=lhc%2Fweb%2Fwiklou.git;a=blobdiff_plain;f=tests%2Fphpunit%2Fincludes%2Flibs%2Frdbms%2Fdatabase%2FDatabaseSQLTest.php;h=5a06cc769fb61a72c95e71f52934ee099ffbe457;hp=981c4075fe4a4b1d1a86bd5bb220e9c24840a87a;hb=3975e04cf4d14d92bdb95d144f7258205df4efb5;hpb=8d68145a16c3bdf1c42dec80b4294592bfd09af0 diff --git a/tests/phpunit/includes/libs/rdbms/database/DatabaseSQLTest.php b/tests/phpunit/includes/libs/rdbms/database/DatabaseSQLTest.php index 981c4075fe..5a06cc769f 100644 --- a/tests/phpunit/includes/libs/rdbms/database/DatabaseSQLTest.php +++ b/tests/phpunit/includes/libs/rdbms/database/DatabaseSQLTest.php @@ -3,6 +3,8 @@ use Wikimedia\Rdbms\IDatabase; use Wikimedia\Rdbms\LikeMatch; use Wikimedia\Rdbms\Database; +use Wikimedia\TestingAccessWrapper; +use Wikimedia\Rdbms\DBUnexpectedError; /** * Test the parts of the Database abstract class that deal @@ -1481,4 +1483,103 @@ class DatabaseSQLTest extends PHPUnit\Framework\TestCase { } } + /** + * @expectedException \Wikimedia\Rdbms\DBTransactionStateError + */ + public function testTransactionErrorState1() { + $wrapper = TestingAccessWrapper::newFromObject( $this->database ); + + $this->database->begin( __METHOD__ ); + $wrapper->trxStatus = Database::STATUS_TRX_ERROR; + $this->database->delete( 'x', [ 'field' => 3 ], __METHOD__ ); + $this->database->commit( __METHOD__ ); + } + + /** + * @covers \Wikimedia\Rdbms\Database::query + */ + public function testTransactionErrorState2() { + $wrapper = TestingAccessWrapper::newFromObject( $this->database ); + + $this->database->startAtomic( __METHOD__ ); + $wrapper->trxStatus = Database::STATUS_TRX_ERROR; + $this->database->rollback( __METHOD__ ); + $this->assertEquals( 0, $this->database->trxLevel() ); + $this->assertEquals( Database::STATUS_TRX_NONE, $wrapper->trxStatus() ); + $this->assertLastSql( 'BEGIN; ROLLBACK' ); + + $this->database->startAtomic( __METHOD__ ); + $this->assertEquals( Database::STATUS_TRX_OK, $wrapper->trxStatus() ); + $this->database->delete( 'x', [ 'field' => 1 ], __METHOD__ ); + $this->database->endAtomic( __METHOD__ ); + $this->assertEquals( Database::STATUS_TRX_NONE, $wrapper->trxStatus() ); + $this->assertLastSql( 'BEGIN; DELETE FROM x WHERE field = \'1\'; COMMIT' ); + $this->assertEquals( 0, $this->database->trxLevel(), 'Use after rollback()' ); + + $this->database->begin( __METHOD__ ); + $this->database->startAtomic( __METHOD__, Database::ATOMIC_CANCELABLE ); + $this->database->update( 'y', [ 'a' => 1 ], [ 'field' => 1 ], __METHOD__ ); + $wrapper->trxStatus = Database::STATUS_TRX_ERROR; + $this->database->cancelAtomic( __METHOD__ ); + $this->assertEquals( Database::STATUS_TRX_OK, $wrapper->trxStatus() ); + $this->database->startAtomic( __METHOD__ ); + $this->database->delete( 'y', [ 'field' => 1 ], __METHOD__ ); + $this->database->endAtomic( __METHOD__ ); + $this->database->commit( __METHOD__ ); + // phpcs:ignore Generic.Files.LineLength + $this->assertLastSql( 'BEGIN; SAVEPOINT wikimedia_rdbms_atomic1; UPDATE y SET a = \'1\' WHERE field = \'1\'; ROLLBACK TO SAVEPOINT wikimedia_rdbms_atomic1; DELETE FROM y WHERE field = \'1\'; COMMIT' ); + $this->assertEquals( 0, $this->database->trxLevel(), 'Use after rollback()' ); + + // Next transaction + $this->database->startAtomic( __METHOD__ ); + $this->assertEquals( Database::STATUS_TRX_OK, $wrapper->trxStatus() ); + $this->database->delete( 'x', [ 'field' => 3 ], __METHOD__ ); + $this->database->endAtomic( __METHOD__ ); + $this->assertEquals( Database::STATUS_TRX_NONE, $wrapper->trxStatus() ); + $this->assertLastSql( 'BEGIN; DELETE FROM x WHERE field = \'3\'; COMMIT' ); + $this->assertEquals( 0, $this->database->trxLevel() ); + } + + /** + * @covers \Wikimedia\Rdbms\Database::close + */ + public function testPrematureClose1() { + $fname = __METHOD__; + $this->database->begin( __METHOD__ ); + $this->database->onTransactionIdle( function () use ( $fname ) { + $this->database->query( 'SELECT 1', $fname ); + } ); + $this->database->delete( 'x', [ 'field' => 3 ], __METHOD__ ); + $this->database->close(); + + $this->assertFalse( $this->database->isOpen() ); + $this->assertLastSql( 'BEGIN; DELETE FROM x WHERE field = \'3\'; COMMIT; SELECT 1' ); + $this->assertEquals( 0, $this->database->trxLevel() ); + } + + /** + * @covers \Wikimedia\Rdbms\Database::close + */ + public function testPrematureClose2() { + try { + $fname = __METHOD__; + $this->database->startAtomic( __METHOD__ ); + $this->database->onTransactionIdle( function () use ( $fname ) { + $this->database->query( 'SELECT 1', $fname ); + } ); + $this->database->delete( 'x', [ 'field' => 3 ], __METHOD__ ); + $this->database->close(); + $this->fail( 'Expected exception not thrown' ); + } catch ( DBUnexpectedError $ex ) { + $this->assertSame( + 'Wikimedia\Rdbms\Database::close: atomic sections ' . + 'DatabaseSQLTest::testPrematureClose2 are still open.', + $ex->getMessage() + ); + } + + $this->assertFalse( $this->database->isOpen() ); + $this->assertLastSql( 'BEGIN; DELETE FROM x WHERE field = \'3\'; ROLLBACK' ); + $this->assertEquals( 0, $this->database->trxLevel() ); + } }