mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
FIX: Introduce readonly transaction test to all database.
This should work on MySQL and PDO; let’s test this.
This commit is contained in:
parent
a7b5de5de4
commit
5531baa87f
@ -21,11 +21,6 @@ class DatabaseTest extends SapphireTest
|
|||||||
|
|
||||||
protected $usesDatabase = true;
|
protected $usesDatabase = true;
|
||||||
|
|
||||||
/**
|
|
||||||
* Disable transactions so that we can test them
|
|
||||||
*/
|
|
||||||
protected $usesTransactions = false;
|
|
||||||
|
|
||||||
public function testDontRequireField()
|
public function testDontRequireField()
|
||||||
{
|
{
|
||||||
$schema = DB::get_schema();
|
$schema = DB::get_schema();
|
||||||
@ -192,52 +187,6 @@ class DatabaseTest extends SapphireTest
|
|||||||
$this->assertTrue($db->canLock('DatabaseTest'), 'Can lock again after releasing it');
|
$this->assertTrue($db->canLock('DatabaseTest'), 'Can lock again after releasing it');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testTransactions()
|
|
||||||
{
|
|
||||||
$conn = DB::get_conn();
|
|
||||||
if (!$conn->supportsTransactions()) {
|
|
||||||
$this->markTestSkipped("DB Doesn't support transactions");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that successful transactions are comitted
|
|
||||||
$obj = new DatabaseTest\MyObject();
|
|
||||||
$failed = false;
|
|
||||||
$conn->withTransaction(
|
|
||||||
function () use (&$obj) {
|
|
||||||
$obj->MyField = 'Save 1';
|
|
||||||
$obj->write();
|
|
||||||
},
|
|
||||||
function () use (&$failed) {
|
|
||||||
$failed = true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
$this->assertEquals('Save 1', DatabaseTest\MyObject::get()->first()->MyField);
|
|
||||||
$this->assertFalse($failed);
|
|
||||||
|
|
||||||
// Test failed transactions are rolled back
|
|
||||||
$ex = null;
|
|
||||||
$failed = false;
|
|
||||||
try {
|
|
||||||
$conn->withTransaction(
|
|
||||||
function () use (&$obj) {
|
|
||||||
$obj->MyField = 'Save 2';
|
|
||||||
$obj->write();
|
|
||||||
throw new Exception("error");
|
|
||||||
},
|
|
||||||
function () use (&$failed) {
|
|
||||||
$failed = true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} catch (Exception $ex) {
|
|
||||||
}
|
|
||||||
$this->assertTrue($failed);
|
|
||||||
$this->assertEquals('Save 1', DatabaseTest\MyObject::get()->first()->MyField);
|
|
||||||
$this->assertInstanceOf('Exception', $ex);
|
|
||||||
$this->assertEquals('error', $ex->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function testFieldTypes()
|
public function testFieldTypes()
|
||||||
{
|
{
|
||||||
// Scaffold some data
|
// Scaffold some data
|
||||||
|
@ -5,6 +5,7 @@ namespace SilverStripe\ORM\Tests;
|
|||||||
use SilverStripe\ORM\DB;
|
use SilverStripe\ORM\DB;
|
||||||
use SilverStripe\ORM\DataObject;
|
use SilverStripe\ORM\DataObject;
|
||||||
use SilverStripe\Dev\SapphireTest;
|
use SilverStripe\Dev\SapphireTest;
|
||||||
|
use SilverStripe\Dev\Deprecation;
|
||||||
use SilverStripe\ORM\Tests\TransactionTest\TestObject;
|
use SilverStripe\ORM\Tests\TransactionTest\TestObject;
|
||||||
|
|
||||||
class TransactionTest extends SapphireTest
|
class TransactionTest extends SapphireTest
|
||||||
@ -17,6 +18,20 @@ class TransactionTest extends SapphireTest
|
|||||||
TransactionTest\TestObject::class,
|
TransactionTest\TestObject::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
private static $originalVersionInfo;
|
||||||
|
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
self::$originalVersionInfo = Deprecation::dump_settings();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown()
|
||||||
|
{
|
||||||
|
Deprecation::restore_settings(self::$originalVersionInfo);
|
||||||
|
parent::tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
public static function setUpBeforeClass()
|
public static function setUpBeforeClass()
|
||||||
{
|
{
|
||||||
parent::setUpBeforeClass();
|
parent::setUpBeforeClass();
|
||||||
@ -25,8 +40,57 @@ class TransactionTest extends SapphireTest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testTransactions()
|
||||||
|
{
|
||||||
|
$conn = DB::get_conn();
|
||||||
|
if (!$conn->supportsTransactions()) {
|
||||||
|
$this->markTestSkipped("DB Doesn't support transactions");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that successful transactions are comitted
|
||||||
|
$obj = new TestObject();
|
||||||
|
$failed = false;
|
||||||
|
$conn->withTransaction(
|
||||||
|
function () use (&$obj) {
|
||||||
|
$obj->Title = 'Save 1';
|
||||||
|
$obj->write();
|
||||||
|
},
|
||||||
|
function () use (&$failed) {
|
||||||
|
$failed = true;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$this->assertEquals('Save 1', TestObject::get()->first()->Title);
|
||||||
|
$this->assertFalse($failed);
|
||||||
|
|
||||||
|
// Test failed transactions are rolled back
|
||||||
|
$ex = null;
|
||||||
|
$failed = false;
|
||||||
|
try {
|
||||||
|
$conn->withTransaction(
|
||||||
|
function () use (&$obj) {
|
||||||
|
$obj->Title = 'Save 2';
|
||||||
|
$obj->write();
|
||||||
|
throw new \Exception("error");
|
||||||
|
},
|
||||||
|
function () use (&$failed) {
|
||||||
|
$failed = true;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (\Exception $ex) {
|
||||||
|
}
|
||||||
|
$this->assertTrue($failed);
|
||||||
|
$this->assertEquals('Save 1', TestObject::get()->first()->Title);
|
||||||
|
$this->assertInstanceOf('Exception', $ex);
|
||||||
|
$this->assertEquals('error', $ex->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
public function testNestedTransaction()
|
public function testNestedTransaction()
|
||||||
{
|
{
|
||||||
|
if (!DB::get_conn()->supportsSavepoints()) {
|
||||||
|
static::markTestSkipped('Current database does not support savepoints');
|
||||||
|
}
|
||||||
|
|
||||||
$this->assertCount(0, TestObject::get());
|
$this->assertCount(0, TestObject::get());
|
||||||
try {
|
try {
|
||||||
DB::get_conn()->withTransaction(function () {
|
DB::get_conn()->withTransaction(function () {
|
||||||
@ -89,4 +153,44 @@ class TransactionTest extends SapphireTest
|
|||||||
$this->assertFalse(is_object($third) && $third->exists());
|
$this->assertFalse(is_object($third) && $third->exists());
|
||||||
$this->assertFalse(is_object($fourth) && $fourth->exists());
|
$this->assertFalse(is_object($fourth) && $fourth->exists());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testReadOnlyTransaction()
|
||||||
|
{
|
||||||
|
if (!DB::get_conn()->supportsTransactions()) {
|
||||||
|
$this->markTestSkipped('Current database is doesn\'t support transactions');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This feature is deprecated in 4.4, but we're still testing it.
|
||||||
|
Deprecation::notification_version('4.3.0');
|
||||||
|
|
||||||
|
$page = new TestObject();
|
||||||
|
$page->Title = 'Read only success';
|
||||||
|
$page->write();
|
||||||
|
|
||||||
|
DB::get_conn()->transactionStart('READ ONLY');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$page = new TestObject();
|
||||||
|
$page->Title = 'Read only page failed';
|
||||||
|
$page->write();
|
||||||
|
DB::get_conn()->transactionEnd();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
//could not write this record
|
||||||
|
//We need to do a rollback or a commit otherwise we'll get error messages
|
||||||
|
DB::get_conn()->transactionRollback();
|
||||||
|
}
|
||||||
|
|
||||||
|
DataObject::flush_and_destroy_cache();
|
||||||
|
|
||||||
|
$success = DataObject::get_one(TestObject::class, "\"Title\"='Read only success'");
|
||||||
|
$fail = DataObject::get_one(TestObject::class, "\"Title\"='Read only page failed'");
|
||||||
|
|
||||||
|
//This page should be in the system
|
||||||
|
$this->assertInternalType('object', $success);
|
||||||
|
$this->assertTrue($success->exists());
|
||||||
|
|
||||||
|
//This page should NOT exist, we had 'read only' permissions
|
||||||
|
$this->assertNull($fail);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user