2020-11-25 17:13:24 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace Illuminate\Tests\Database;
|
|
|
|
|
|
|
|
|
|
use Illuminate\Database\DatabaseTransactionsManager;
|
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
|
|
|
|
|
|
class DatabaseTransactionsManagerTest extends TestCase
|
|
|
|
|
{
|
|
|
|
|
public function testBeginningTransactions()
|
|
|
|
|
{
|
2025-09-30 12:50:37 +03:00
|
|
|
$manager = new DatabaseTransactionsManager;
|
2020-11-25 17:13:24 +02:00
|
|
|
|
|
|
|
|
$manager->begin('default', 1);
|
|
|
|
|
$manager->begin('default', 2);
|
|
|
|
|
$manager->begin('admin', 1);
|
|
|
|
|
|
2023-11-10 16:49:32 -03:00
|
|
|
$this->assertCount(3, $manager->getPendingTransactions());
|
|
|
|
|
$this->assertSame('default', $manager->getPendingTransactions()[0]->connection);
|
|
|
|
|
$this->assertEquals(1, $manager->getPendingTransactions()[0]->level);
|
|
|
|
|
$this->assertSame('default', $manager->getPendingTransactions()[1]->connection);
|
|
|
|
|
$this->assertEquals(2, $manager->getPendingTransactions()[1]->level);
|
|
|
|
|
$this->assertSame('admin', $manager->getPendingTransactions()[2]->connection);
|
|
|
|
|
$this->assertEquals(1, $manager->getPendingTransactions()[2]->level);
|
2020-11-25 17:13:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testRollingBackTransactions()
|
|
|
|
|
{
|
2025-09-30 12:50:37 +03:00
|
|
|
$manager = new DatabaseTransactionsManager;
|
2020-11-25 17:13:24 +02:00
|
|
|
|
|
|
|
|
$manager->begin('default', 1);
|
|
|
|
|
$manager->begin('default', 2);
|
|
|
|
|
$manager->begin('admin', 1);
|
|
|
|
|
|
2020-11-25 18:26:55 +02:00
|
|
|
$manager->rollback('default', 1);
|
2020-11-25 17:13:24 +02:00
|
|
|
|
2023-11-10 16:49:32 -03:00
|
|
|
$this->assertCount(2, $manager->getPendingTransactions());
|
2020-11-25 17:13:24 +02:00
|
|
|
|
2023-11-10 16:49:32 -03:00
|
|
|
$this->assertSame('default', $manager->getPendingTransactions()[0]->connection);
|
|
|
|
|
$this->assertEquals(1, $manager->getPendingTransactions()[0]->level);
|
2020-11-25 17:13:24 +02:00
|
|
|
|
2023-11-10 16:49:32 -03:00
|
|
|
$this->assertSame('admin', $manager->getPendingTransactions()[1]->connection);
|
|
|
|
|
$this->assertEquals(1, $manager->getPendingTransactions()[1]->level);
|
2020-11-25 17:13:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testRollingBackTransactionsAllTheWay()
|
|
|
|
|
{
|
2025-09-30 12:50:37 +03:00
|
|
|
$manager = new DatabaseTransactionsManager;
|
2020-11-25 17:13:24 +02:00
|
|
|
|
|
|
|
|
$manager->begin('default', 1);
|
|
|
|
|
$manager->begin('default', 2);
|
|
|
|
|
$manager->begin('admin', 1);
|
|
|
|
|
|
2020-11-25 18:26:55 +02:00
|
|
|
$manager->rollback('default', 0);
|
2020-11-25 17:13:24 +02:00
|
|
|
|
2023-11-10 16:49:32 -03:00
|
|
|
$this->assertCount(1, $manager->getPendingTransactions());
|
2020-11-25 17:13:24 +02:00
|
|
|
|
2023-11-10 16:49:32 -03:00
|
|
|
$this->assertSame('admin', $manager->getPendingTransactions()[0]->connection);
|
|
|
|
|
$this->assertEquals(1, $manager->getPendingTransactions()[0]->level);
|
2020-11-25 17:13:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testCommittingTransactions()
|
|
|
|
|
{
|
2025-09-30 12:50:37 +03:00
|
|
|
$manager = new DatabaseTransactionsManager;
|
2020-11-25 17:13:24 +02:00
|
|
|
|
|
|
|
|
$manager->begin('default', 1);
|
|
|
|
|
$manager->begin('default', 2);
|
|
|
|
|
$manager->begin('admin', 1);
|
2023-11-23 17:45:07 -06:00
|
|
|
$manager->begin('admin', 2);
|
2020-11-25 17:13:24 +02:00
|
|
|
|
2023-11-23 17:45:07 -06:00
|
|
|
$manager->commit('default', 2, 1);
|
|
|
|
|
$executedTransactions = $manager->commit('default', 1, 0);
|
2020-11-25 17:13:24 +02:00
|
|
|
|
2023-11-23 17:45:07 -06:00
|
|
|
$executedAdminTransactions = $manager->commit('admin', 2, 1);
|
2020-11-25 17:13:24 +02:00
|
|
|
|
2023-11-23 17:45:07 -06:00
|
|
|
$this->assertCount(1, $manager->getPendingTransactions()); // One pending "admin" transaction left...
|
2024-04-12 21:01:45 +08:00
|
|
|
$this->assertCount(2, $executedTransactions); // Two committed transactions on "default"
|
|
|
|
|
$this->assertCount(0, $executedAdminTransactions); // Zero executed committed transactions on "default"
|
2023-11-23 17:45:07 -06:00
|
|
|
|
|
|
|
|
// Level 2 "admin" callback has been staged...
|
2023-11-10 16:49:32 -03:00
|
|
|
$this->assertSame('admin', $manager->getCommittedTransactions()[0]->connection);
|
2023-11-23 17:45:07 -06:00
|
|
|
$this->assertEquals(2, $manager->getCommittedTransactions()[0]->level);
|
|
|
|
|
|
|
|
|
|
// Level 1 "admin" callback still pending...
|
|
|
|
|
$this->assertSame('admin', $manager->getPendingTransactions()[0]->connection);
|
|
|
|
|
$this->assertEquals(1, $manager->getPendingTransactions()[0]->level);
|
2020-11-25 17:13:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testCallbacksAreAddedToTheCurrentTransaction()
|
|
|
|
|
{
|
|
|
|
|
$callbacks = [];
|
|
|
|
|
|
2025-09-30 12:50:37 +03:00
|
|
|
$manager = new DatabaseTransactionsManager;
|
2020-11-25 17:13:24 +02:00
|
|
|
|
|
|
|
|
$manager->begin('default', 1);
|
|
|
|
|
|
|
|
|
|
$manager->addCallback(function () use (&$callbacks) {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$manager->begin('default', 2);
|
|
|
|
|
|
|
|
|
|
$manager->begin('admin', 1);
|
|
|
|
|
|
|
|
|
|
$manager->addCallback(function () use (&$callbacks) {
|
|
|
|
|
});
|
|
|
|
|
|
2023-11-10 16:49:32 -03:00
|
|
|
$this->assertCount(1, $manager->getPendingTransactions()[0]->getCallbacks());
|
|
|
|
|
$this->assertCount(0, $manager->getPendingTransactions()[1]->getCallbacks());
|
|
|
|
|
$this->assertCount(1, $manager->getPendingTransactions()[2]->getCallbacks());
|
2020-11-25 17:13:24 +02:00
|
|
|
}
|
|
|
|
|
|
2025-09-10 18:07:37 +03:30
|
|
|
public function testCallbacksRunInFifoOrder()
|
|
|
|
|
{
|
2025-09-30 12:50:37 +03:00
|
|
|
$manager = new DatabaseTransactionsManager;
|
2025-09-10 18:07:37 +03:30
|
|
|
|
|
|
|
|
$order = [];
|
|
|
|
|
|
|
|
|
|
$manager->begin('default', 1);
|
|
|
|
|
|
|
|
|
|
$manager->addCallback(function () use (&$order) {
|
|
|
|
|
$order[] = 1;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$manager->addCallback(function () use (&$order) {
|
|
|
|
|
$order[] = 2;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$manager->addCallback(function () use (&$order) {
|
|
|
|
|
$order[] = 3;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$manager->commit('default', 1, 0);
|
|
|
|
|
|
|
|
|
|
$this->assertSame([1, 2, 3], $order);
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-25 17:13:24 +02:00
|
|
|
public function testCommittingTransactionsExecutesCallbacks()
|
|
|
|
|
{
|
|
|
|
|
$callbacks = [];
|
|
|
|
|
|
2025-09-30 12:50:37 +03:00
|
|
|
$manager = new DatabaseTransactionsManager;
|
2020-11-25 17:13:24 +02:00
|
|
|
|
|
|
|
|
$manager->begin('default', 1);
|
|
|
|
|
|
|
|
|
|
$manager->addCallback(function () use (&$callbacks) {
|
|
|
|
|
$callbacks[] = ['default', 1];
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$manager->begin('default', 2);
|
|
|
|
|
|
|
|
|
|
$manager->addCallback(function () use (&$callbacks) {
|
|
|
|
|
$callbacks[] = ['default', 2];
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$manager->begin('admin', 1);
|
|
|
|
|
|
2023-11-23 17:45:07 -06:00
|
|
|
$manager->commit('default', 2, 1);
|
|
|
|
|
$manager->commit('default', 1, 0);
|
2020-11-25 17:13:24 +02:00
|
|
|
|
|
|
|
|
$this->assertCount(2, $callbacks);
|
2023-11-23 17:45:07 -06:00
|
|
|
$this->assertEquals(['default', 2], $callbacks[0]);
|
|
|
|
|
$this->assertEquals(['default', 1], $callbacks[1]);
|
2020-11-25 17:13:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testCommittingExecutesOnlyCallbacksOfTheConnection()
|
|
|
|
|
{
|
|
|
|
|
$callbacks = [];
|
|
|
|
|
|
2025-09-30 12:50:37 +03:00
|
|
|
$manager = new DatabaseTransactionsManager;
|
2020-11-25 17:13:24 +02:00
|
|
|
|
|
|
|
|
$manager->begin('default', 1);
|
|
|
|
|
|
|
|
|
|
$manager->addCallback(function () use (&$callbacks) {
|
|
|
|
|
$callbacks[] = ['default', 1];
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$manager->begin('default', 2);
|
|
|
|
|
$manager->begin('admin', 1);
|
|
|
|
|
|
|
|
|
|
$manager->addCallback(function () use (&$callbacks) {
|
|
|
|
|
$callbacks[] = ['admin', 1];
|
|
|
|
|
});
|
|
|
|
|
|
2023-11-23 17:45:07 -06:00
|
|
|
$manager->commit('default', 2, 1);
|
|
|
|
|
$manager->commit('default', 1, 0);
|
2020-11-25 17:13:24 +02:00
|
|
|
|
|
|
|
|
$this->assertCount(1, $callbacks);
|
|
|
|
|
$this->assertEquals(['default', 1], $callbacks[0]);
|
|
|
|
|
}
|
2020-11-26 15:11:40 +02:00
|
|
|
|
|
|
|
|
public function testCallbackIsExecutedIfNoTransactions()
|
|
|
|
|
{
|
|
|
|
|
$callbacks = [];
|
|
|
|
|
|
2025-09-30 12:50:37 +03:00
|
|
|
$manager = new DatabaseTransactionsManager;
|
2020-11-26 15:11:40 +02:00
|
|
|
|
|
|
|
|
$manager->addCallback(function () use (&$callbacks) {
|
|
|
|
|
$callbacks[] = ['default', 1];
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$this->assertCount(1, $callbacks);
|
|
|
|
|
$this->assertEquals(['default', 1], $callbacks[0]);
|
|
|
|
|
}
|
2023-11-10 16:49:32 -03:00
|
|
|
|
2025-04-19 00:44:40 +09:00
|
|
|
public function testCallbacksForRollbackAreAddedToTheCurrentTransaction()
|
|
|
|
|
{
|
|
|
|
|
$callbacks = [];
|
|
|
|
|
|
2025-09-30 12:50:37 +03:00
|
|
|
$manager = new DatabaseTransactionsManager;
|
2025-04-19 00:44:40 +09:00
|
|
|
|
|
|
|
|
$manager->begin('default', 1);
|
|
|
|
|
|
|
|
|
|
$manager->addCallbackForRollback(function () use (&$callbacks) {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$manager->begin('default', 2);
|
|
|
|
|
|
|
|
|
|
$manager->begin('admin', 1);
|
|
|
|
|
|
|
|
|
|
$manager->addCallbackForRollback(function () use (&$callbacks) {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$this->assertCount(1, $manager->getPendingTransactions()[0]->getCallbacksForRollback());
|
|
|
|
|
$this->assertCount(0, $manager->getPendingTransactions()[1]->getCallbacksForRollback());
|
|
|
|
|
$this->assertCount(1, $manager->getPendingTransactions()[2]->getCallbacksForRollback());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testRollbackTransactionsExecutesCallbacks()
|
|
|
|
|
{
|
|
|
|
|
$callbacks = [];
|
|
|
|
|
|
2025-09-30 12:50:37 +03:00
|
|
|
$manager = new DatabaseTransactionsManager;
|
2025-04-19 00:44:40 +09:00
|
|
|
|
|
|
|
|
$manager->begin('default', 1);
|
|
|
|
|
|
|
|
|
|
$manager->addCallbackForRollback(function () use (&$callbacks) {
|
|
|
|
|
$callbacks[] = ['default', 1];
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$manager->begin('default', 2);
|
|
|
|
|
|
|
|
|
|
$manager->addCallbackForRollback(function () use (&$callbacks) {
|
|
|
|
|
$callbacks[] = ['default', 2];
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$manager->begin('admin', 1);
|
|
|
|
|
|
|
|
|
|
$manager->rollback('default', 1);
|
|
|
|
|
$manager->rollback('default', 0);
|
|
|
|
|
|
|
|
|
|
$this->assertCount(2, $callbacks);
|
|
|
|
|
$this->assertEquals(['default', 2], $callbacks[0]);
|
|
|
|
|
$this->assertEquals(['default', 1], $callbacks[1]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testRollbackExecutesOnlyCallbacksOfTheConnection()
|
|
|
|
|
{
|
|
|
|
|
$callbacks = [];
|
|
|
|
|
|
2025-09-30 12:50:37 +03:00
|
|
|
$manager = new DatabaseTransactionsManager;
|
2025-04-19 00:44:40 +09:00
|
|
|
|
|
|
|
|
$manager->begin('default', 1);
|
|
|
|
|
|
|
|
|
|
$manager->addCallbackForRollback(function () use (&$callbacks) {
|
|
|
|
|
$callbacks[] = ['default', 1];
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$manager->begin('default', 2);
|
|
|
|
|
$manager->begin('admin', 1);
|
|
|
|
|
|
|
|
|
|
$manager->addCallbackForRollback(function () use (&$callbacks) {
|
|
|
|
|
$callbacks[] = ['admin', 1];
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$manager->rollback('default', 1);
|
|
|
|
|
$manager->rollback('default', 0);
|
|
|
|
|
|
|
|
|
|
$this->assertCount(1, $callbacks);
|
|
|
|
|
$this->assertEquals(['default', 1], $callbacks[0]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testCallbackForRollbackIsNotExecutedIfNoTransactions()
|
|
|
|
|
{
|
|
|
|
|
$callbacks = [];
|
|
|
|
|
|
2025-09-30 12:50:37 +03:00
|
|
|
$manager = new DatabaseTransactionsManager;
|
2025-04-19 00:44:40 +09:00
|
|
|
|
|
|
|
|
$manager->addCallbackForRollback(function () use (&$callbacks) {
|
|
|
|
|
$callbacks[] = ['default', 1];
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$this->assertCount(0, $callbacks);
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-10 16:49:32 -03:00
|
|
|
public function testStageTransactions()
|
|
|
|
|
{
|
2025-09-30 12:50:37 +03:00
|
|
|
$manager = new DatabaseTransactionsManager;
|
2023-11-10 16:49:32 -03:00
|
|
|
|
|
|
|
|
$manager->begin('default', 1);
|
|
|
|
|
$manager->begin('admin', 1);
|
|
|
|
|
|
|
|
|
|
$this->assertCount(2, $manager->getPendingTransactions());
|
|
|
|
|
|
|
|
|
|
$pendingTransactions = $manager->getPendingTransactions();
|
|
|
|
|
|
|
|
|
|
$this->assertEquals(1, $pendingTransactions[0]->level);
|
|
|
|
|
$this->assertEquals('default', $pendingTransactions[0]->connection);
|
|
|
|
|
$this->assertEquals(1, $pendingTransactions[1]->level);
|
|
|
|
|
$this->assertEquals('admin', $pendingTransactions[1]->connection);
|
|
|
|
|
|
2023-11-23 16:30:10 +01:00
|
|
|
$manager->stageTransactions('default', 1);
|
2023-11-10 16:49:32 -03:00
|
|
|
|
|
|
|
|
$this->assertCount(1, $manager->getPendingTransactions());
|
|
|
|
|
$this->assertCount(1, $manager->getCommittedTransactions());
|
|
|
|
|
$this->assertEquals('default', $manager->getCommittedTransactions()[0]->connection);
|
|
|
|
|
|
2023-11-23 16:30:10 +01:00
|
|
|
$manager->stageTransactions('admin', 1);
|
2023-11-10 16:49:32 -03:00
|
|
|
|
|
|
|
|
$this->assertCount(0, $manager->getPendingTransactions());
|
|
|
|
|
$this->assertCount(2, $manager->getCommittedTransactions());
|
|
|
|
|
$this->assertEquals('admin', $manager->getCommittedTransactions()[1]->connection);
|
|
|
|
|
}
|
2023-11-23 16:30:10 +01:00
|
|
|
|
|
|
|
|
public function testStageTransactionsOnlyStagesTheTransactionsAtOrAboveTheGivenLevel()
|
|
|
|
|
{
|
2025-09-30 12:50:37 +03:00
|
|
|
$manager = new DatabaseTransactionsManager;
|
2023-11-23 16:30:10 +01:00
|
|
|
|
|
|
|
|
$manager->begin('default', 1);
|
|
|
|
|
$manager->begin('default', 2);
|
|
|
|
|
$manager->begin('default', 3);
|
|
|
|
|
$manager->stageTransactions('default', 2);
|
|
|
|
|
|
|
|
|
|
$this->assertCount(1, $manager->getPendingTransactions());
|
|
|
|
|
$this->assertCount(2, $manager->getCommittedTransactions());
|
|
|
|
|
}
|
2020-11-25 17:13:24 +02:00
|
|
|
}
|