rdbms: allow cancelation of dangling nested atomic sections
[lhc/web/wiklou.git] / tests / phpunit / includes / libs / rdbms / database / DatabaseSQLTest.php
index 665e953..e4f4f7b 100644 (file)
@@ -6,6 +6,7 @@ use Wikimedia\Rdbms\Database;
 use Wikimedia\TestingAccessWrapper;
 use Wikimedia\Rdbms\DBTransactionStateError;
 use Wikimedia\Rdbms\DBUnexpectedError;
+use Wikimedia\Rdbms\DBTransactionError;
 
 /**
  * Test the parts of the Database abstract class that deal
@@ -1402,22 +1403,33 @@ class DatabaseSQLTest extends PHPUnit\Framework\TestCase {
                // phpcs:ignore Generic.Files.LineLength
                $this->assertLastSql( 'BEGIN; SAVEPOINT wikimedia_rdbms_atomic1; ROLLBACK TO SAVEPOINT wikimedia_rdbms_atomic1; COMMIT' );
 
-               $this->database->doAtomicSection( __METHOD__, function () {
-               } );
+               $noOpCallack = function () {
+               };
+
+               $this->database->doAtomicSection( __METHOD__, $noOpCallack, IDatabase::ATOMIC_CANCELABLE );
+               $this->assertLastSql( 'BEGIN; COMMIT' );
+
+               $this->database->doAtomicSection( __METHOD__, $noOpCallack );
                $this->assertLastSql( 'BEGIN; COMMIT' );
 
                $this->database->begin( __METHOD__ );
-               $this->database->doAtomicSection( __METHOD__, function () {
-               } );
+               $this->database->doAtomicSection( __METHOD__, $noOpCallack, IDatabase::ATOMIC_CANCELABLE );
                $this->database->rollback( __METHOD__ );
                // phpcs:ignore Generic.Files.LineLength
                $this->assertLastSql( 'BEGIN; SAVEPOINT wikimedia_rdbms_atomic1; RELEASE SAVEPOINT wikimedia_rdbms_atomic1; ROLLBACK' );
 
                $this->database->begin( __METHOD__ );
                try {
-                       $this->database->doAtomicSection( __METHOD__, function () {
-                               throw new RuntimeException( 'Test exception' );
-                       } );
+                       $this->database->doAtomicSection(
+                               __METHOD__,
+                               function () {
+                                       $this->database->startAtomic( 'inner_func1' );
+                                       $this->database->startAtomic( 'inner_func2' );
+
+                                       throw new RuntimeException( 'Test exception' );
+                               },
+                               IDatabase::ATOMIC_CANCELABLE
+                       );
                        $this->fail( 'Expected exception not thrown' );
                } catch ( RuntimeException $ex ) {
                        $this->assertSame( 'Test exception', $ex->getMessage() );
@@ -1425,6 +1437,21 @@ class DatabaseSQLTest extends PHPUnit\Framework\TestCase {
                $this->database->commit( __METHOD__ );
                // phpcs:ignore Generic.Files.LineLength
                $this->assertLastSql( 'BEGIN; SAVEPOINT wikimedia_rdbms_atomic1; ROLLBACK TO SAVEPOINT wikimedia_rdbms_atomic1; COMMIT' );
+
+               $this->database->begin( __METHOD__ );
+               try {
+                       $this->database->doAtomicSection(
+                               __METHOD__,
+                               function () {
+                                       throw new RuntimeException( 'Test exception' );
+                               }
+                       );
+                       $this->fail( 'Test exception not thrown' );
+               } catch ( RuntimeException $ex ) {
+                       $this->assertSame( 'Test exception', $ex->getMessage() );
+               }
+               $this->database->rollback( __METHOD__ );
+               $this->assertLastSql( 'BEGIN; ROLLBACK' );
        }
 
        public static function provideAtomicSectionMethodsForErrors() {
@@ -1445,7 +1472,7 @@ class DatabaseSQLTest extends PHPUnit\Framework\TestCase {
                        $this->fail( 'Expected exception not thrown' );
                } catch ( DBUnexpectedError $ex ) {
                        $this->assertSame(
-                               'No atomic transaction is open (got ' . __METHOD__ . ').',
+                               'No atomic section is open (got ' . __METHOD__ . ').',
                                $ex->getMessage()
                        );
                }
@@ -1463,7 +1490,8 @@ class DatabaseSQLTest extends PHPUnit\Framework\TestCase {
                        $this->fail( 'Expected exception not thrown' );
                } catch ( DBUnexpectedError $ex ) {
                        $this->assertSame(
-                               'Invalid atomic section ended (got ' . __METHOD__ . ').',
+                               'Invalid atomic section ended (got ' . __METHOD__ . ' but expected ' .
+                                       __METHOD__ . 'X' . ').',
                                $ex->getMessage()
                        );
                }
@@ -1476,10 +1504,11 @@ class DatabaseSQLTest extends PHPUnit\Framework\TestCase {
                $this->database->startAtomic( __METHOD__ );
                try {
                        $this->database->cancelAtomic( __METHOD__ );
+                       $this->database->select( 'test', '1', [], __METHOD__ );
                        $this->fail( 'Expected exception not thrown' );
-               } catch ( DBUnexpectedError $ex ) {
+               } catch ( DBTransactionError $ex ) {
                        $this->assertSame(
-                               'Uncancelable atomic section canceled (got ' . __METHOD__ . ').',
+                               'Cannot execute query from ' . __METHOD__ . ' while transaction status is ERROR.',
                                $ex->getMessage()
                        );
                }