From d2964e387186a9832dc259662f334c5def8c2dae Mon Sep 17 00:00:00 2001
From: Christian Kuhn <lolli@schwarzbu.ch>
Date: Tue, 27 Feb 2024 18:59:22 +0100
Subject: [PATCH] [TASK] Avoid phpunit @requires annotation

Substitute with a PHP attribute.

Resolves: #103219
Releases: main
Change-Id: Ie589404f797a880fc8e27480a2dd95c3f0420427
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/83152
Tested-by: core-ci <typo3@b13.com>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Oliver Klee <typo3-coding@oliverklee.de>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Oliver Klee <typo3-coding@oliverklee.de>
---
 Build/Scripts/annotationChecker.php           |  5 +-
 .../Cache/Backend/RedisBackendTest.php        | 31 ++----------
 .../Backend/RedisSessionBackendTest.php       | 48 ++-----------------
 .../Locking/SemaphoreLockStrategyTest.php     |  6 +--
 4 files changed, 11 insertions(+), 79 deletions(-)

diff --git a/Build/Scripts/annotationChecker.php b/Build/Scripts/annotationChecker.php
index be593104f35f..6e4ef6131aad 100755
--- a/Build/Scripts/annotationChecker.php
+++ b/Build/Scripts/annotationChecker.php
@@ -29,9 +29,6 @@ require_once __DIR__ . '/../../vendor/autoload.php';
 
 class NodeVisitor extends NodeVisitorAbstract
 {
-    /**
-     * @var array
-     */
     public array $matches = [];
 
     public function enterNode(Node $node)
@@ -54,7 +51,7 @@ class NodeVisitor extends NodeVisitorAbstract
                     // PHPDocumentor 2 tags
                     'author', 'category', 'copyright', 'deprecated', 'example', 'internal', 'license', 'link', 'param', 'property', 'return', 'see', 'since', 'throws', 'todo', 'TODO', 'var', 'version',
                     // PHPUnit & codeception tags
-                    'depends', 'requires', 'env',
+                    'depends', 'env',
                     // PHPCheckStyle
                     'SuppressWarnings', 'noinspection',
                     // Extbase related
diff --git a/typo3/sysext/core/Tests/Functional/Cache/Backend/RedisBackendTest.php b/typo3/sysext/core/Tests/Functional/Cache/Backend/RedisBackendTest.php
index 674432d6e99a..244473fb9aad 100644
--- a/typo3/sysext/core/Tests/Functional/Cache/Backend/RedisBackendTest.php
+++ b/typo3/sysext/core/Tests/Functional/Cache/Backend/RedisBackendTest.php
@@ -17,6 +17,7 @@ declare(strict_types=1);
 
 namespace TYPO3\CMS\Core\Tests\Functional\Cache\Backend;
 
+use PHPUnit\Framework\Attributes\RequiresPhpExtension;
 use PHPUnit\Framework\Attributes\Test;
 use Psr\Log\LoggerInterface;
 use TYPO3\CMS\Core\Cache\Backend\RedisBackend;
@@ -25,15 +26,7 @@ use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
 use TYPO3\CMS\Core\Utility\StringUtility;
 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
 
-/**
- * Test case for the cache to redis backend
- *
- * Warning:
- * These functional tests use and flush redis database numbers 0 and 1 on the
- * redis host specified by environment variable typo3RedisHost
- *
- * @requires extension redis
- */
+#[RequiresPhpExtension('redis')]
 final class RedisBackendTest extends FunctionalTestCase
 {
     protected bool $initializeDatabase = false;
@@ -49,9 +42,6 @@ final class RedisBackendTest extends FunctionalTestCase
         parent::setUp();
     }
 
-    /**
-     * Sets up the redis cache backend used for testing
-     */
     protected function setUpSubject(array $backendOptions = []): RedisBackend
     {
         // We know this env is set, otherwise setUp() would skip the tests
@@ -72,17 +62,13 @@ final class RedisBackendTest extends FunctionalTestCase
         return $subject;
     }
 
-    /**
-     * Sets up a test-internal redis connection to check implementation details
-     */
-    protected function setUpRedis(): \Redis
+    private function setUpRedis(): \Redis
     {
         // We know this env is set, otherwise setUp() would skip the tests
         $redisHost = getenv('typo3TestingRedisHost');
         // If typo3TestingRedisPort env is set, use it, otherwise fall back to standard port
         $env = getenv('typo3TestingRedisPort');
         $redisPort = is_string($env) ? (int)$env : 6379;
-
         $redis = new \Redis();
         $redis->connect($redisHost, $redisPort);
         return $redis;
@@ -93,7 +79,6 @@ final class RedisBackendTest extends FunctionalTestCase
     {
         $this->expectException(\InvalidArgumentException::class);
         $this->expectExceptionCode(1279763057);
-
         $this->setUpSubject(['database' => 'foo']);
     }
 
@@ -102,7 +87,6 @@ final class RedisBackendTest extends FunctionalTestCase
     {
         $this->expectException(\InvalidArgumentException::class);
         $this->expectExceptionCode(1279763534);
-
         $this->setUpSubject(['database' => -1]);
     }
 
@@ -111,7 +95,6 @@ final class RedisBackendTest extends FunctionalTestCase
     {
         $this->expectException(\InvalidArgumentException::class);
         $this->expectExceptionCode(1289679153);
-
         $this->setUpSubject(['compression' => 'foo']);
     }
 
@@ -120,7 +103,6 @@ final class RedisBackendTest extends FunctionalTestCase
     {
         $this->expectException(\InvalidArgumentException::class);
         $this->expectExceptionCode(1289679154);
-
         $this->setUpSubject(['compressionLevel' => 'foo']);
     }
 
@@ -129,7 +111,6 @@ final class RedisBackendTest extends FunctionalTestCase
     {
         $this->expectException(\InvalidArgumentException::class);
         $this->expectExceptionCode(1289679155);
-
         $this->setUpSubject(['compressionLevel' => 11]);
     }
 
@@ -138,7 +119,6 @@ final class RedisBackendTest extends FunctionalTestCase
     {
         $this->expectException(\InvalidArgumentException::class);
         $this->expectExceptionCode(1487849315);
-
         $this->setUpSubject(['connectionTimeout' => 'foo']);
     }
 
@@ -147,7 +127,6 @@ final class RedisBackendTest extends FunctionalTestCase
     {
         $this->expectException(\InvalidArgumentException::class);
         $this->expectExceptionCode(1487849326);
-
         $this->setUpSubject(['connectionTimeout' => -1]);
     }
 
@@ -156,7 +135,6 @@ final class RedisBackendTest extends FunctionalTestCase
     {
         $this->expectException(\InvalidArgumentException::class);
         $this->expectExceptionCode(1377006651);
-
         $subject = $this->setUpSubject();
         $subject->set([], 'data');
     }
@@ -166,7 +144,6 @@ final class RedisBackendTest extends FunctionalTestCase
     {
         $this->expectException(InvalidDataException::class);
         $this->expectExceptionCode(1279469941);
-
         $subject = $this->setUpSubject();
         $subject->set(StringUtility::getUniqueId('identifier'), []);
     }
@@ -176,7 +153,6 @@ final class RedisBackendTest extends FunctionalTestCase
     {
         $this->expectException(\InvalidArgumentException::class);
         $this->expectExceptionCode(1279487573);
-
         $subject = $this->setUpSubject();
         $subject->set(StringUtility::getUniqueId('identifier'), 'data', [], -42);
     }
@@ -186,7 +162,6 @@ final class RedisBackendTest extends FunctionalTestCase
     {
         $this->expectException(\InvalidArgumentException::class);
         $this->expectExceptionCode(1279488008);
-
         $subject = $this->setUpSubject();
         $subject->set(StringUtility::getUniqueId('identifier'), 'data', [], []);
     }
diff --git a/typo3/sysext/core/Tests/Functional/Session/Backend/RedisSessionBackendTest.php b/typo3/sysext/core/Tests/Functional/Session/Backend/RedisSessionBackendTest.php
index c6b61c994717..954f9419d92b 100644
--- a/typo3/sysext/core/Tests/Functional/Session/Backend/RedisSessionBackendTest.php
+++ b/typo3/sysext/core/Tests/Functional/Session/Backend/RedisSessionBackendTest.php
@@ -17,6 +17,7 @@ declare(strict_types=1);
 
 namespace TYPO3\CMS\Core\Tests\Functional\Session\Backend;
 
+use PHPUnit\Framework\Attributes\RequiresPhpExtension;
 use PHPUnit\Framework\Attributes\Test;
 use TYPO3\CMS\Core\Session\Backend\Exception\SessionNotCreatedException;
 use TYPO3\CMS\Core\Session\Backend\Exception\SessionNotFoundException;
@@ -24,27 +25,15 @@ use TYPO3\CMS\Core\Session\Backend\Exception\SessionNotUpdatedException;
 use TYPO3\CMS\Core\Session\Backend\RedisSessionBackend;
 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
 
-/**
- * @requires extension redis
- */
+#[RequiresPhpExtension('redis')]
 final class RedisSessionBackendTest extends FunctionalTestCase
 {
     protected bool $initializeDatabase = false;
 
-    /**
-     * @var RedisSessionBackend Prepared and connected redis test subject
-     */
-    protected $subject;
-
-    /**
-     * @var \Redis
-     */
-    protected $redis;
+    private RedisSessionBackend $subject;
+    private \Redis $redis;
 
-    /**
-     * @var array
-     */
-    protected $testSessionRecord = [
+    protected array $testSessionRecord = [
         // RedisSessionBackend::hash('randomSessionId') with encryption key 12345
         'ses_id' => '21c0e911565a67315cdc384889c470fd291feafbfa62e31ecf7409430640bc7a',
         'ses_userid' => 1,
@@ -52,33 +41,26 @@ final class RedisSessionBackendTest extends FunctionalTestCase
         'ses_data' => 'a:2:{s:3:"foo";s:3:"bar";s:3:"boo";s:3:"far";}',
     ];
 
-    /**
-     * Set configuration for RedisSessionBackend
-     */
     protected function setUp(): void
     {
         parent::setUp();
         $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'] = '12345';
-
         if (!getenv('typo3TestingRedisHost')) {
             self::markTestSkipped('environment variable "typo3TestingRedisHost" must be set to run this test');
         }
         // Note we assume that if that typo3TestingRedisHost env is set, we can use that for testing,
         // there is no test to see if the daemon is actually up and running. Tests will fail if env
         // is set but daemon is down.
-
         // We know this env is set, otherwise setUp() would skip the tests
         $redisHost = getenv('typo3TestingRedisHost');
         // If typo3TestingRedisPort env is set, use it, otherwise fall back to standard port
         $env = getenv('typo3TestingRedisPort');
         $redisPort = is_string($env) ? (int)$env : 6379;
-
         $this->redis = new \Redis();
         $this->redis->connect($redisHost, $redisPort);
         $this->redis->select(0);
         // Clear db to ensure no sessions exist currently
         $this->redis->flushDB();
-
         $this->subject = new RedisSessionBackend();
         $this->subject->initialize(
             'default',
@@ -108,9 +90,7 @@ final class RedisSessionBackendTest extends FunctionalTestCase
     public function sessionDataIsStoredProperly(): void
     {
         $record = $this->subject->set('randomSessionId', $this->testSessionRecord);
-
         $expected = array_merge($this->testSessionRecord, ['ses_tstamp' => $GLOBALS['EXEC_TIME']]);
-
         self::assertEquals($record, $expected);
         $result = $this->subject->get('randomSessionId');
         self::assertSame($expected, $result);
@@ -120,9 +100,7 @@ final class RedisSessionBackendTest extends FunctionalTestCase
     public function anonymousSessionDataIsStoredProperly(): void
     {
         $record = $this->subject->set('randomSessionId', array_merge($this->testSessionRecord, ['ses_userid' => 0]));
-
         $expected = array_merge($this->testSessionRecord, ['ses_userid' => 0, 'ses_tstamp' => $GLOBALS['EXEC_TIME']]);
-
         self::assertEquals($record, $expected);
         self::assertSame($expected, $this->subject->get('randomSessionId'));
     }
@@ -139,7 +117,6 @@ final class RedisSessionBackendTest extends FunctionalTestCase
     public function mergeSessionDataWithNewData(): void
     {
         $this->subject->set('randomSessionId', $this->testSessionRecord);
-
         $updateData = [
             'ses_data' => serialize(['foo' => 'baz', 'idontwantto' => 'set the world on fire']),
             'ses_tstamp' => $GLOBALS['EXEC_TIME'],
@@ -155,9 +132,7 @@ final class RedisSessionBackendTest extends FunctionalTestCase
     {
         $this->expectException(SessionNotCreatedException::class);
         $this->expectExceptionCode(1481895647);
-
         $this->subject->set('randomSessionId', $this->testSessionRecord);
-
         $newData = array_merge($this->testSessionRecord, ['ses_data' => serialize(['foo' => 'baz', 'idontwantto' => 'set the world on fire'])]);
         $this->subject->set('randomSessionId', $newData);
     }
@@ -166,16 +141,12 @@ final class RedisSessionBackendTest extends FunctionalTestCase
     public function cannotChangeSessionId(): void
     {
         $this->subject->set('randomSessionId', $this->testSessionRecord);
-
         $newSessionId = 'newRandomSessionId';
         $newData = array_merge($this->testSessionRecord, ['ses_id' => $newSessionId]);
-
         // old session id has to exist, no exception must be thrown at this point
         $this->subject->get('randomSessionId');
-
         // Change session id
         $this->subject->update('randomSessionId', $newData);
-
         // no session with key newRandomSessionId should exist
         $this->expectException(SessionNotFoundException::class);
         $this->expectExceptionCode(1481885583);
@@ -186,10 +157,8 @@ final class RedisSessionBackendTest extends FunctionalTestCase
     public function sessionGetsDestroyed(): void
     {
         $this->subject->set('randomSessionId', $this->testSessionRecord);
-
         // Remove session
         self::assertTrue($this->subject->remove('randomSessionId'));
-
         // Check if session was really removed
         $this->expectException(SessionNotFoundException::class);
         $this->expectExceptionCode(1481885583);
@@ -201,7 +170,6 @@ final class RedisSessionBackendTest extends FunctionalTestCase
     {
         $this->subject->set('randomSessionId', $this->testSessionRecord);
         $this->subject->set('randomSessionId2', $this->testSessionRecord);
-
         // Check if session was really removed
         self::assertCount(2, $this->subject->getAll());
     }
@@ -212,10 +180,8 @@ final class RedisSessionBackendTest extends FunctionalTestCase
         $GLOBALS['EXEC_TIME'] = 150;
         $authenticatedSession = array_merge($this->testSessionRecord, ['ses_id' => 'authenticatedSession']);
         $anonymousSession = array_merge($this->testSessionRecord, ['ses_id' => 'anonymousSession', 'ses_userid' => 0]);
-
         $this->subject->set('authenticatedSession', $authenticatedSession);
         $this->subject->set('anonymousSession', $anonymousSession);
-
         // Assert that we set authenticated session correctly
         self::assertSame(
             $authenticatedSession['ses_data'],
@@ -225,18 +191,15 @@ final class RedisSessionBackendTest extends FunctionalTestCase
             $authenticatedSession['ses_userid'],
             $this->subject->get('authenticatedSession')['ses_userid']
         );
-
         // assert that we set anonymous session correctly
         self::assertSame(
             $anonymousSession['ses_data'],
             $this->subject->get('anonymousSession')['ses_data']
         );
-
         // Run the garbage collection
         $GLOBALS['EXEC_TIME'] = 200;
         // 150 + 10 < 200 but 150 + 60 >= 200
         $this->subject->collectGarbage(60, 10);
-
         // Authenticated session should still be there
         self::assertSame(
             $authenticatedSession['ses_data'],
@@ -246,7 +209,6 @@ final class RedisSessionBackendTest extends FunctionalTestCase
             $authenticatedSession['ses_userid'],
             $this->subject->get('authenticatedSession')['ses_userid']
         );
-
         // Non-authenticated session should be removed
         $this->expectException(SessionNotFoundException::class);
         $this->expectExceptionCode(1481885583);
diff --git a/typo3/sysext/core/Tests/Unit/Locking/SemaphoreLockStrategyTest.php b/typo3/sysext/core/Tests/Unit/Locking/SemaphoreLockStrategyTest.php
index 3d079f9ea18a..9e1a8b515d63 100644
--- a/typo3/sysext/core/Tests/Unit/Locking/SemaphoreLockStrategyTest.php
+++ b/typo3/sysext/core/Tests/Unit/Locking/SemaphoreLockStrategyTest.php
@@ -17,17 +17,16 @@ declare(strict_types=1);
 
 namespace TYPO3\CMS\Core\Tests\Unit\Locking;
 
+use PHPUnit\Framework\Attributes\RequiresFunction;
 use PHPUnit\Framework\Attributes\Test;
 use TYPO3\CMS\Core\Locking\SemaphoreLockStrategy;
 use TYPO3\CMS\Core\Locking\SimpleLockStrategy;
 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
 
-/**
- * @requires function sem_get
- */
 final class SemaphoreLockStrategyTest extends UnitTestCase
 {
     #[Test]
+    #[RequiresFunction('sem_get')]
     public function acquireGetsSemaphore(): void
     {
         $lock = new SemaphoreLockStrategy('99999');
@@ -46,7 +45,6 @@ final class SemaphoreLockStrategyTest extends UnitTestCase
     public function setPriority(): void
     {
         $GLOBALS['TYPO3_CONF_VARS']['SYS']['locking']['strategies'][SemaphoreLockStrategy::class]['priority'] = 10;
-
         self::assertEquals(10, SemaphoreLockStrategy::getPriority());
         unset($GLOBALS['TYPO3_CONF_VARS']['SYS']['locking']['strategies'][SemaphoreLockStrategy::class]['priority']);
     }
-- 
GitLab