Fatal Error in RulesDebugLoggerChannelTest.php with Drupal 11

Created on 2 July 2024, 2 months ago
Updated 16 July 2024, about 2 months ago

Problem/Motivation

When running PHPUnit tests on Drupal 11 for RulesDebugLoggerChannelTest.php, the following fatal error occurs:

PHP Fatal error: Declaration of Drupal\Tests\rules\Unit\TestSessionBase::setId($id) must be compatible with Symfony\Component\HttpFoundation\Session\SessionInterface::setId(string $id): void in /Users/user1/drupal11.0.0-beta1/docroot/modules/contrib/rules/tests/src/Unit/TestSessionBase.php on line 109

Steps to reproduce

  • Download the latest Drupal 11 project using drupal/recommended-project version 11.0.0-beta1.
  • Download the drupal/core-dev development dependencies.
  • Download the 4.0.x release of the Rules module.
  • Run the PHPUnit tests for the class RulesDebugLoggerChannelTest.

Proposed resolution

The error arises because the method signature in the SessionInterface from Symfony 7.0 has been updated to include type hints, which differ from the previous versions. The interface now contains the following methods with return types:

public function setId(string $id): void;
public function setName(string $name): void;
public function save(): void;
public function set(string $name, mixed $value): void;
public function replace(array $attributes): void;
public function clear(): void;
public function registerBag(SessionBagInterface $bag): void;

Earlier this method doesn't contain any return types in Symfony 6.4. See here.

In the Rules module, the TestSessionBase class implements the SessionInterface, but it lacks the new type hints, causing compatibility issues with Symfony 7.0.

To maintain compatibility with both Drupal Core 10.1.x (Symfony 6.4) and Drupal Core 11.x (Symfony 7.0), where each has different type hints, a direct conditional type hinting isn't feasible in PHP

Alternative Approach

Upon further investigation, it was noted that the TestSession class is only used in these tests and nowhere else. Therefore, it is feasible to use Symfony's MockArraySessionStorage class to store session logs, allowing us to eliminate the TestSession class entirely.

🐛 Bug report
Status

Fixed

Version

4.0

Component

Rules Core

Created by

🇮🇳India vishalkhode

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @vishalkhode
  • Merge request !49Fixed fatal error that appeas in Drupal 11. → (Merged) created by vishalkhode
  • Pipeline finished with Success
    2 months ago
    Total: 278s
    #213859
  • Status changed to Needs review 2 months ago
  • 🇮🇳India vishalkhode

    @TR: Can you review this.

  • 🇺🇸United States TR Cascadia

    IIRC the TestSession class was written because we needed two functional methods on the Session for storing and retrieving the Session data, but an actual Session couldn't be instantiated in a Unit test. The methods we didn't need were required by the interfaced, but didn't contain anything.

    Your alternate solution looks good.

    Why did you remove the array keys? They are there to serve as documentation, and because if a test case fails the key name is displayed in the error output, helping debugging. If you want to remove the keys, then at the very least the data provider method's documentation block should contain a detailed description of the array structure in the @return text. That way we know what that random data in each of those 8 array elements is supposed to contain.

  • 🇺🇸United States TR Cascadia

    Oh, and now I recall more details about TestSession. It was split into two classes because during the D9->D10 transition Drupal core changed from Symfony 4 to Symfony 6. Symfony 6 required PHP 8, and the SessionInterface in Symfony 6 used the "mixed" return type that didn't exist in D9/PHP7. So in order to support both D9/PHP 7/Symfony 4 and D10/PHP 8/Symfony 6 with the same code base, we had to make a base TestSession that worked in both versions and make a subclass that was declared conditionally depending on what Drupal version was being used. I just removed that conditional code last week in the 4.0.x branch since we no longer have to support D9. See #3265360: [D10] Test failure

    Regardless, if you can address the array keys then I can merge this.

  • Pipeline finished with Success
    2 months ago
    Total: 391s
    #214221
  • 🇮🇳India vishalkhode

    @TR: I've added them back. The reason I removed earlier, because when running tests, I was seeing following deprecation messages:

    * Providing invalid named argument $min_psr3_level for method Drupal\Tests\rules\Unit\RulesDebugLoggerChannelTest::testLog() is deprecated and will not be supported in PHPUnit 11.0.
    * Providing invalid named argument $expected_system_logs for method Drupal\Tests\rules\Unit\RulesDebugLoggerChannelTest::testLog() is deprecated and will not be supported in PHPUnit 11.0.
    * Providing invalid named argument $expected_screen_logs for method Drupal\Tests\rules\Unit\RulesDebugLoggerChannelTest::testLog() is deprecated and will not be supported in PHPUnit 11.0.
    /Users/user1/drupal11.0.0-beta1/docroot/modules/contrib/rules/tests/src/Unit/RulesDebugLoggerChannelTest.php:94
    

    I earlier read above message as: Providing named argument is deprecated, but the actual message was Providing invalid named argument is deprecated. So, I've now updated the MR and fixed the deprecations. Though fixing that deprecation was not part of this ticket, if you need I can create a separate ticket and add this changes there, if not, then feel free to merge the MR.

    Why did you remove the array keys? They are there to serve as documentation, and because if a test case fails the key name is displayed in the error output, helping debugging.

  • Pipeline finished with Skipped
    2 months ago
    #214231
  • Status changed to Fixed 2 months ago
  • 🇺🇸United States TR Cascadia

    Very nice work. Thanks. Merged!

  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024