Browse Source

Change wasNestedTransactionRolledback to protected

Also improve related tests cases.
chinpei215 9 years ago
parent
commit
01ce700b20
2 changed files with 73 additions and 33 deletions
  1. 11 9
      src/Database/Connection.php
  2. 62 24
      tests/TestCase/Database/ConnectionTest.php

+ 11 - 9
src/Database/Connection.php

@@ -98,7 +98,7 @@ class Connection implements ConnectionInterface
      *
      * @var \Cake\Database\Exception\NestedTransactionRollbackException|null
      */
-    protected $_nestedTransactionRollbackException = null;
+    protected $nestedTransactionRollbackException = null;
 
     /**
      * Constructor.
@@ -450,7 +450,7 @@ class Connection implements ConnectionInterface
             $this->_driver->beginTransaction();
             $this->_transactionLevel = 0;
             $this->_transactionStarted = true;
-            $this->_nestedTransactionRollbackException = null;
+            $this->nestedTransactionRollbackException = null;
 
             return;
         }
@@ -474,11 +474,13 @@ class Connection implements ConnectionInterface
 
         if ($this->_transactionLevel === 0) {
             if ($this->wasNestedTransactionRolledback()) {
-                throw $this->_nestedTransactionRollbackException;
+                $e = $this->nestedTransactionRollbackException;
+                $this->nestedTransactionRollbackException = null;
+                throw $e;
             }
 
             $this->_transactionStarted = false;
-            $this->_nestedTransactionRollbackException = null;
+            $this->nestedTransactionRollbackException = null;
             if ($this->_logQueries) {
                 $this->log('COMMIT');
             }
@@ -514,7 +516,7 @@ class Connection implements ConnectionInterface
         if ($this->_transactionLevel === 0 || $toBeginning) {
             $this->_transactionLevel = 0;
             $this->_transactionStarted = false;
-            $this->_nestedTransactionRollbackException = null;
+            $this->nestedTransactionRollbackException = null;
             if ($this->_logQueries) {
                 $this->log('ROLLBACK');
             }
@@ -526,8 +528,8 @@ class Connection implements ConnectionInterface
         $savePoint = $this->_transactionLevel--;
         if ($useSavePoint) {
             $this->rollbackSavepoint($savePoint);
-        } elseif ($this->_nestedTransactionRollbackException === null) {
-            $this->_nestedTransactionRollbackException = new NestedTransactionRollbackException();
+        } elseif ($this->nestedTransactionRollbackException === null) {
+            $this->nestedTransactionRollbackException = new NestedTransactionRollbackException();
         }
 
         return true;
@@ -702,9 +704,9 @@ class Connection implements ConnectionInterface
      *
      * @return bool
      */
-    public function wasNestedTransactionRolledback()
+    protected function wasNestedTransactionRolledback()
     {
-        return $this->_nestedTransactionRollbackException instanceof NestedTransactionRollbackException;
+        return $this->nestedTransactionRollbackException instanceof NestedTransactionRollbackException;
     }
 
     /**

+ 62 - 24
tests/TestCase/Database/ConnectionTest.php

@@ -20,6 +20,7 @@ use Cake\Database\Driver\Mysql;
 use Cake\Database\Exception\NestedTransactionRollbackException;
 use Cake\Datasource\ConnectionManager;
 use Cake\TestSuite\TestCase;
+use ReflectionMethod;
 
 /**
  * Tests Connection class
@@ -29,6 +30,21 @@ class ConnectionTest extends TestCase
 
     public $fixtures = ['core.things'];
 
+    /**
+     * Where the NestedTransactionRollbackException was created.
+     *
+     * @var int
+     */
+    protected $rollbackSourceLine = -1;
+
+    /**
+     * Internal states of nested transaction.
+     *
+     * @var array
+     */
+    protected $nestedTransactionStates = [];
+
+
     public function setUp()
     {
         parent::setUp();
@@ -1030,50 +1046,60 @@ class ConnectionTest extends TestCase
      * a NestedTransactionRollbackException.
      *
      * @return void
-     * @expectedException \Cake\Database\Exception\NestedTransactionRollbackException
-     * @expectedExceptionMessage Cannot commit transaction - rollback() has been already called in the nested transaction
      */
     public function testNestedTransactionRollbackExceptionThrown()
     {
-        // ROLLBACK -> COMMIT
-        $this->connection->transactional(function () {
+        $this->rollbackSourceLine = -1;
+
+        $e = null;
+        try {
             $this->connection->transactional(function () {
-                return false;
+                $this->connection->transactional(function () {
+                    return false;
+                });
+                $this->rollbackSourceLine = __LINE__ - 1;
+
+                return true;
             });
 
-            return true;
-        });
+            $this->fail('NestedTransactionRollbackException should be thrown');
+        } catch (NestedTransactionRollbackException $e) {
+        }
+
+        $trace = $e->getTrace();
+        $this->assertEquals(__FILE__, $trace[1]['file']);
+        $this->assertEquals($this->rollbackSourceLine, $trace[1]['line']);
     }
 
     /**
-     * Tests mor detail about that not allowed nesting of rollback/commit
-     * operations throws a NestedTransactionRollbackException by trace.
+     * Tests more detail about that not allowed nesting of rollback/commit
+     * operations throws a NestedTransactionRollbackException.
      *
      * @return void
      */
-    public function testNestedTransactionRollbackExceptionByTrace()
+    public function testNestedTransactionStates()
     {
-        $rollbackSourceLine = -1;
-        $nestedTransactionStates = [];
+        $this->rollbackSourceLine = -1;
+        $this->nestedTransactionStates = [];
 
         $e = null;
         try {
-            $this->connection->transactional(function () use (&$rollbackSourceLine, &$nestedTransactionStates) {
-                $nestedTransactionStates[] = $this->connection->wasNestedTransactionRolledback();
+            $this->connection->transactional(function () {
+                $this->pushNestedTransactionState();
 
                 $this->connection->transactional(function () {
                     return true;
                 });
 
-                $this->connection->transactional(function () use (&$rollbackSourceLine, &$nestedTransactionStates) {
-                    $nestedTransactionStates[] = $this->connection->wasNestedTransactionRolledback();
+                $this->connection->transactional(function () {
+                    $this->pushNestedTransactionState();
 
                     $this->connection->transactional(function () {
                         return false;
                     });
-                    $rollbackSourceLine = __LINE__ - 1;
+                    $this->rollbackSourceLine = __LINE__ - 1;
 
-                    $nestedTransactionStates[] = $this->connection->wasNestedTransactionRolledback();
+                    $this->pushNestedTransactionState();
 
                     return true;
                 });
@@ -1082,22 +1108,34 @@ class ConnectionTest extends TestCase
                     return false;
                 });
 
-                $nestedTransactionStates[] = $this->connection->wasNestedTransactionRolledback();
+                $this->pushNestedTransactionState();
 
                 return true;
             });
+
+            $this->fail('NestedTransactionRollbackException should be thrown');
         } catch (NestedTransactionRollbackException $e) {
         }
 
-        $nestedTransactionStates[] = $this->connection->wasNestedTransactionRolledback();
-
-        $this->assertInstanceOf(NestedTransactionRollbackException::class, $e);
+        $this->pushNestedTransactionState();
 
-        $this->assertSame([false, false, true, true, false], $nestedTransactionStates);
+        $this->assertSame([false, false, true, true, false], $this->nestedTransactionStates);
         $this->assertFalse($this->connection->inTransaction());
 
         $trace = $e->getTrace();
         $this->assertEquals(__FILE__, $trace[1]['file']);
-        $this->assertEquals($rollbackSourceLine, $trace[1]['line']);
+        $this->assertEquals($this->rollbackSourceLine, $trace[1]['line']);
+    }
+
+    /**
+     * Helper method to trace nested transaction states.
+     *
+     * @return void
+     */
+    public function pushNestedTransactionState()
+    {
+        $method = new ReflectionMethod($this->connection, 'wasNestedTransactionRolledback');
+        $method->setAccessible(true);
+        $this->nestedTransactionStates[] = $method->invoke($this->connection);
     }
 }