From 8f4771385c204fcfcb3a9c7f39b21bb9b1cf54c8 Mon Sep 17 00:00:00 2001 From: Steve Boyd Date: Wed, 5 Jun 2024 17:28:05 +1200 Subject: [PATCH 1/2] ENH Use class name instead of self --- src/TestSessionController.php | 2 +- src/TestSessionEnvironment.php | 16 ++++++++++------ src/TestSessionState.php | 6 +++--- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/TestSessionController.php b/src/TestSessionController.php index f5d9947..c1d464e 100644 --- a/src/TestSessionController.php +++ b/src/TestSessionController.php @@ -326,7 +326,7 @@ class TestSessionController extends Controller } /** - * As with {@link self::start()}, if you want to extend the functionality of this, then look at + * As with {@link TestSessionController::start()}, if you want to extend the functionality of this, then look at * {@link TestSessionEnvironent::endTestSession()} as the extension points have moved to there now that the logic * is there. */ diff --git a/src/TestSessionEnvironment.php b/src/TestSessionEnvironment.php index 4dc08f1..7a067bd 100644 --- a/src/TestSessionEnvironment.php +++ b/src/TestSessionEnvironment.php @@ -63,7 +63,7 @@ class TestSessionEnvironment /** * @var string The original database name, before we overrode it with our tmpdb. * - * Used in {@link self::resetDatabaseName()} when we want to restore the normal DB connection. + * Used in {@link TestSessionEnvironment::resetDatabaseName()} when we want to restore the normal DB connection. */ private $oldDatabaseName; @@ -137,14 +137,16 @@ class TestSessionEnvironment /** * Creates a temp database, sets up any extra requirements, and writes the state file. The database will be - * connected to as part of {@link self::applyState()}, so if you're continuing script execution after calling this + * connected to as part of {@link TestSessionEnvironment::applyState()}, so if you're continuing script + * execution after calling this * method, be aware that the database will be different - so various things may break (e.g. administrator logins * using the SS_DEFAULT_USERNAME / SS_DEFAULT_PASSWORD constants). * * If something isn't explicitly handled here, and needs special handling, then it should be taken care of by an * extension to TestSessionEnvironment. You can either extend onBeforeStartTestSession() or * onAfterStartTestSession(). Alternatively, for more fine-grained control, you can also extend - * onBeforeApplyState() and onAfterApplyState(). See the {@link self::applyState()} method for more. + * onBeforeApplyState() and onAfterApplyState(). See the {@link TestSessionEnvironment::applyState()} + * method for more. * * @param array $state An array of test state options to write. * @param mixed $id @@ -445,7 +447,8 @@ class TestSessionEnvironment /** * Cleans up the test session state by restoring the normal database connect (for the rest of this request, if any) - * and removes the {@link self::$test_state_file} so that future requests don't use this test state. + * and removes the {@link TestSessionEnvironment::$test_state_file} so that future requests don't use this + * test state. * * Can be extended by implementing either onBeforeEndTestSession() or onAfterEndTestSession(). * @@ -514,7 +517,8 @@ class TestSessionEnvironment } /** - * Reset the database connection to use the original database. Called by {@link self::endTestSession()}. + * Reset the database connection to use the original database. + * Called by {@link TestSessionEnvironment::endTestSession()}. */ public function resetDatabaseName() { @@ -532,7 +536,7 @@ class TestSessionEnvironment } /** - * @return stdClass Data as taken from the JSON object in {@link self::loadFromFile()} + * @return stdClass Data as taken from the JSON object in {@link TestSessionEnvironment::loadFromFile()} */ public function getState() { diff --git a/src/TestSessionState.php b/src/TestSessionState.php index 7cc3835..8efa5ac 100644 --- a/src/TestSessionState.php +++ b/src/TestSessionState.php @@ -33,7 +33,7 @@ class TestSessionState extends DataObject { $schema = DataObject::getSchema(); - $update = SQLUpdate::create(sprintf('"%s"', $schema->tableName(self::class))) + $update = SQLUpdate::create(sprintf('"%s"', $schema->tableName(TestSessionState::class))) ->addWhere(['ID' => 1]) ->assignSQL('"PendingRequests"', '"PendingRequests" + 1'); @@ -50,10 +50,10 @@ class TestSessionState extends DataObject { $schema = DataObject::getSchema(); - $update = SQLUpdate::create(sprintf('"%s"', $schema->tableName(self::class))) + $update = SQLUpdate::create(sprintf('"%s"', $schema->tableName(TestSessionState::class))) ->addWhere(['ID' => 1]) ->assignSQL('"PendingRequests"', '"PendingRequests" - 1') - ->assign('"LastResponseTimestamp"', self::millitime()); + ->assign('"LastResponseTimestamp"', TestSessionState::millitime()); $update->execute(); } From d7c4b0c420ee7eef95bec2335a48fb07c2c0b5ff Mon Sep 17 00:00:00 2001 From: Steve Boyd Date: Thu, 26 Sep 2024 15:19:07 +1200 Subject: [PATCH 2/2] FIX Ensure primary connection is updated with temporary database --- _config.php | 2 +- src/TestSessionEnvironment.php | 25 +++++++++++++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/_config.php b/_config.php index a372c88..ec27655 100644 --- a/_config.php +++ b/_config.php @@ -12,7 +12,7 @@ TestSessionEnvironment::singleton()->loadFromFile(); */ if (class_exists('Resque_Event') && class_exists('SSResqueRun')) { Resque_Event::listen('beforeFork', function ($data) { - $databaseConfig = DB::getConfig(); + $databaseConfig = DB::getConfig(DB::CONN_PRIMARY); // Reconnect to the database - this may connect to the old DB first, but is required because these processes // are long-lived, and MySQL connections often get closed in between worker runs. We need to connect before diff --git a/src/TestSessionEnvironment.php b/src/TestSessionEnvironment.php index 7a067bd..567714a 100644 --- a/src/TestSessionEnvironment.php +++ b/src/TestSessionEnvironment.php @@ -272,7 +272,7 @@ class TestSessionEnvironment $this->extend('onBeforeApplyState', $state); // back up source - $databaseConfig = DB::getConfig(); + $databaseConfig = DB::getConfig(DB::CONN_PRIMARY); $this->oldDatabaseName = $databaseConfig['database']; // Load existing state from $this->state into $state, if there is any @@ -523,9 +523,9 @@ class TestSessionEnvironment public function resetDatabaseName() { if ($this->oldDatabaseName) { - $databaseConfig = DB::getConfig(); + $databaseConfig = DB::getConfig(DB::CONN_PRIMARY); $databaseConfig['database'] = $this->oldDatabaseName; - DB::setConfig($databaseConfig); + DB::setConfig($databaseConfig, DB::CONN_PRIMARY); $conn = DB::get_conn(); @@ -568,7 +568,7 @@ class TestSessionEnvironment $state = $this->getState(); } - $databaseConfig = DB::getConfig(); + $databaseConfig = DB::getConfig(DB::CONN_PRIMARY); if (isset($state->database) && $state->database) { if (!DB::get_conn()) { @@ -579,14 +579,14 @@ class TestSessionEnvironment } // Connect to database - DB::connect($databaseConfig); + $this->connectToDB($databaseConfig); } else { // We've already connected to the database, do a fast check to see what database we're currently using $db = DB::get_conn()->getSelectedDatabase(); if (isset($state->database) && $db != $state->database) { $this->oldDatabaseName = $databaseConfig['database']; $databaseConfig['database'] = $state->database; - DB::connect($databaseConfig); + $this->connectToDB($databaseConfig); } } } @@ -622,4 +622,17 @@ class TestSessionEnvironment return true; } + + private function connectToDB(array $databaseConfig): void + { + if (method_exists(DB::class, 'hasConfig')) { + // CMS 5.4+ - ensure we connect the primary connection and not a replica + // which can happen if we use the default value of DB::CONN_DYNAMIC + // and there is a replica database configured + DB::connect($databaseConfig, DB::CONN_PRIMARY); + } else { + // CMS 5.3 and below do not support replica connections, use 'default' connection + DB::connect($databaseConfig); + } + } }