function DatabaseStorageTest::testConcurrent

Same name in other branches
  1. 9 core/tests/Drupal/KernelTests/Core/KeyValueStore/DatabaseStorageTest.php \Drupal\KernelTests\Core\KeyValueStore\DatabaseStorageTest::testConcurrent()
  2. 11.x core/tests/Drupal/KernelTests/Core/KeyValueStore/DatabaseStorageTest.php \Drupal\KernelTests\Core\KeyValueStore\DatabaseStorageTest::testConcurrent()

Tests asynchronous table creation.

File

core/tests/Drupal/KernelTests/Core/KeyValueStore/DatabaseStorageTest.php, line 40

Class

DatabaseStorageTest
Tests the key-value database storage.

Namespace

Drupal\KernelTests\Core\KeyValueStore

Code

public function testConcurrent() : void {
    $this->markTestSkipped("Skipped due to frequent random test failures. See https://www.drupal.org/project/drupal/issues/3398063");
    if (!function_exists('pcntl_fork')) {
        $this->markTestSkipped('Requires the pcntl_fork() function');
    }
    $functions = [];
    for ($i = 1; $i <= 10; $i++) {
        $functions[] = 'set';
        $functions[] = 'getAll';
    }
    $default_connection = Database::getConnectionInfo();
    Database::removeConnection('default');
    $time_to_start = microtime(TRUE) + 0.1;
    // This loop creates a new fork to set or get key values keys.
    foreach ($functions as $i => $function) {
        $pid = pcntl_fork();
        if ($pid == -1) {
            $this->fail("Error forking");
        }
        elseif ($pid == 0) {
            Database::addConnectionInfo('default' . $i, 'default', $default_connection['default']);
            Database::setActiveConnection('default' . $i);
            // Create a new factory using the new connection to avoid problems with
            // forks closing the database connections.
            $factory = new KeyValueDatabaseFactory($this->container
                ->get('serialization.phpserialize'), Database::getConnection());
            $store = $factory->get('test');
            // Sleep so that all the forks start at the same time.
            usleep((int) (($time_to_start - microtime(TRUE)) * 1000000));
            if ($function === 'getAll') {
                $this->assertIsArray($store->getAll());
            }
            else {
                $this->assertNull($store->set('foo' . $i, 'bar'));
            }
            exit;
        }
    }
    // This while loop holds the parent process until all the child threads
    // are complete - at which point the script continues to execute.
    while (pcntl_waitpid(0, $status) != -1) {
    }
    Database::addConnectionInfo('default', 'default', $default_connection['default']);
    $factory = new KeyValueDatabaseFactory($this->container
        ->get('serialization.phpserialize'), Database::getConnection());
    $store = $factory->get('test');
    $this->assertCount(10, $store->getAll());
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.