From 7871102fa4e2982634376671090dc73a30860ded Mon Sep 17 00:00:00 2001
From: phenaproxima <phenaproxima@205645.no-reply.drupal.org>
Date: Wed, 29 Jun 2022 20:40:16 +0000
Subject: [PATCH] Issue #3263223 by phenaproxima: All kernel tests should use a
 virtual project

---
 ...agesInstalledWithComposerValidatorTest.php |  1 -
 .../UpdatePackagesTypeValidatorTest.php       |  1 -
 .../Validator/UpdateReleaseValidatorTest.php  |  1 -
 package_manager/package_manager.services.yml  |  1 -
 .../Validator/WritableFileSystemValidator.php | 23 ++++-----
 .../ComposerExecutableValidatorTest.php       |  3 --
 .../Kernel/ComposerSettingsValidatorTest.php  |  1 -
 .../src/Kernel/DiskSpaceValidatorTest.php     |  4 +-
 .../src/Kernel/LockFileValidatorTest.php      |  1 -
 .../src/Kernel/MultisiteValidatorTest.php     |  2 -
 .../Kernel/PackageManagerKernelTestBase.php   | 16 ++----
 .../Kernel/PathExcluder/GitExcluderTest.php   |  2 -
 .../SiteConfigurationExcluderTest.php         |  1 -
 .../PathExcluder/SiteFilesExcluderTest.php    |  1 -
 .../SqliteDatabaseExcluderTest.php            | 15 +++---
 .../PathExcluder/TestSiteExcluderTest.php     |  1 -
 .../VendorHardeningExcluderTest.php           |  1 -
 .../Kernel/PendingUpdatesValidatorTest.php    | 10 ----
 .../src/Kernel/SettingsValidatorTest.php      |  4 --
 .../tests/src/Kernel/StageEventsTest.php      |  3 --
 .../tests/src/Kernel/StageOwnershipTest.php   |  4 --
 .../tests/src/Kernel/StageTest.php            |  4 ++
 .../tests/src/Kernel/SymlinkValidatorTest.php | 12 +----
 .../WritableFileSystemValidatorTest.php       | 50 +++----------------
 tests/src/Kernel/CronUpdaterTest.php          |  4 --
 .../CronFrequencyValidatorTest.php            |  4 --
 .../ReadinessValidationManagerTest.php        |  3 --
 .../ScaffoldFilePermissionsValidatorTest.php  |  3 +-
 .../StagedDatabaseUpdateValidatorTest.php     |  5 +-
 .../StagedProjectsValidatorTest.php           |  1 -
 .../VersionPolicyValidatorTest.php            | 11 ----
 31 files changed, 39 insertions(+), 154 deletions(-)

diff --git a/automatic_updates_extensions/tests/src/Kernel/Validator/PackagesInstalledWithComposerValidatorTest.php b/automatic_updates_extensions/tests/src/Kernel/Validator/PackagesInstalledWithComposerValidatorTest.php
index ae19a6db45..34598ecf42 100644
--- a/automatic_updates_extensions/tests/src/Kernel/Validator/PackagesInstalledWithComposerValidatorTest.php
+++ b/automatic_updates_extensions/tests/src/Kernel/Validator/PackagesInstalledWithComposerValidatorTest.php
@@ -36,7 +36,6 @@ class PackagesInstalledWithComposerValidatorTest extends AutomaticUpdatesExtensi
     // type validator.
     $this->disableValidators[] = 'automatic_updates_extensions.validator.packages_type';
     parent::setUp();
-    $this->createTestProject();
     $this->activeDir = $this->container->get('package_manager.path_locator')
       ->getProjectRoot();
   }
diff --git a/automatic_updates_extensions/tests/src/Kernel/Validator/UpdatePackagesTypeValidatorTest.php b/automatic_updates_extensions/tests/src/Kernel/Validator/UpdatePackagesTypeValidatorTest.php
index 95fc564bcb..1d99721d74 100644
--- a/automatic_updates_extensions/tests/src/Kernel/Validator/UpdatePackagesTypeValidatorTest.php
+++ b/automatic_updates_extensions/tests/src/Kernel/Validator/UpdatePackagesTypeValidatorTest.php
@@ -25,7 +25,6 @@ class UpdatePackagesTypeValidatorTest extends AutomaticUpdatesExtensionsKernelTe
     $this->disableValidators[] = 'automatic_updates_extensions.validator.target_release';
     $this->disableValidators[] = 'automatic_updates_extensions.validator.packages_installed_with_composer';
     parent::setUp();
-    $this->createTestProject();
   }
 
   /**
diff --git a/automatic_updates_extensions/tests/src/Kernel/Validator/UpdateReleaseValidatorTest.php b/automatic_updates_extensions/tests/src/Kernel/Validator/UpdateReleaseValidatorTest.php
index 35706c57ee..4b0714b0bb 100644
--- a/automatic_updates_extensions/tests/src/Kernel/Validator/UpdateReleaseValidatorTest.php
+++ b/automatic_updates_extensions/tests/src/Kernel/Validator/UpdateReleaseValidatorTest.php
@@ -20,7 +20,6 @@ class UpdateReleaseValidatorTest extends AutomaticUpdatesExtensionsKernelTestBas
   protected function setUp(): void {
     $this->disableValidators[] = 'automatic_updates_extensions.validator.packages_installed_with_composer';
     parent::setUp();
-    $this->createTestProject();
   }
 
   /**
diff --git a/package_manager/package_manager.services.yml b/package_manager/package_manager.services.yml
index b3b7d6ef4d..bef3aec5c9 100644
--- a/package_manager/package_manager.services.yml
+++ b/package_manager/package_manager.services.yml
@@ -179,7 +179,6 @@ services:
     class: Drupal\package_manager\Validator\WritableFileSystemValidator
     arguments:
       - '@package_manager.path_locator'
-      - '%app.root%'
       - '@string_translation'
     tags:
       - { name: event_subscriber }
diff --git a/package_manager/src/Validator/WritableFileSystemValidator.php b/package_manager/src/Validator/WritableFileSystemValidator.php
index 24ccc24186..4b60c0cb7b 100644
--- a/package_manager/src/Validator/WritableFileSystemValidator.php
+++ b/package_manager/src/Validator/WritableFileSystemValidator.php
@@ -2,10 +2,10 @@
 
 namespace Drupal\package_manager\Validator;
 
+use Drupal\Core\StringTranslation\TranslationInterface;
 use Drupal\package_manager\Event\PreCreateEvent;
 use Drupal\package_manager\Event\PreOperationStageEvent;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
-use Drupal\Core\StringTranslation\TranslationInterface;
 use Drupal\package_manager\PathLocator;
 
 /**
@@ -22,26 +22,16 @@ class WritableFileSystemValidator implements PreOperationStageValidatorInterface
    */
   protected $pathLocator;
 
-  /**
-   * The Drupal root.
-   *
-   * @var string
-   */
-  protected $appRoot;
-
   /**
    * Constructs a WritableFileSystemValidator object.
    *
    * @param \Drupal\package_manager\PathLocator $path_locator
    *   The path locator service.
-   * @param string $app_root
-   *   The Drupal root.
    * @param \Drupal\Core\StringTranslation\TranslationInterface $translation
    *   The translation service.
    */
-  public function __construct(PathLocator $path_locator, string $app_root, TranslationInterface $translation) {
+  public function __construct(PathLocator $path_locator, TranslationInterface $translation) {
     $this->pathLocator = $path_locator;
-    $this->appRoot = $app_root;
     $this->setStringTranslation($translation);
   }
 
@@ -56,9 +46,14 @@ class WritableFileSystemValidator implements PreOperationStageValidatorInterface
   public function validateStagePreOperation(PreOperationStageEvent $event): void {
     $messages = [];
 
-    if (!is_writable($this->appRoot)) {
+    $drupal_root = $this->pathLocator->getProjectRoot();
+    $web_root = $this->pathLocator->getWebRoot();
+    if ($web_root) {
+      $drupal_root .= DIRECTORY_SEPARATOR . $web_root;
+    }
+    if (!is_writable($drupal_root)) {
       $messages[] = $this->t('The Drupal directory "@dir" is not writable.', [
-        '@dir' => $this->appRoot,
+        '@dir' => $drupal_root,
       ]);
     }
 
diff --git a/package_manager/tests/src/Kernel/ComposerExecutableValidatorTest.php b/package_manager/tests/src/Kernel/ComposerExecutableValidatorTest.php
index 1548f5da64..a9d60ac959 100644
--- a/package_manager/tests/src/Kernel/ComposerExecutableValidatorTest.php
+++ b/package_manager/tests/src/Kernel/ComposerExecutableValidatorTest.php
@@ -31,9 +31,6 @@ class ComposerExecutableValidatorTest extends PackageManagerKernelTestBase {
   protected function setUp(): void {
     $this->composerRunner = $this->prophesize(ComposerRunnerInterface::class);
     parent::setUp();
-    // Use a virtual project so that the test isn't affected by symlinks or
-    // other unexpected things that might be present in the running code base.
-    $this->createTestProject();
   }
 
   /**
diff --git a/package_manager/tests/src/Kernel/ComposerSettingsValidatorTest.php b/package_manager/tests/src/Kernel/ComposerSettingsValidatorTest.php
index 071bbfc823..3226b72583 100644
--- a/package_manager/tests/src/Kernel/ComposerSettingsValidatorTest.php
+++ b/package_manager/tests/src/Kernel/ComposerSettingsValidatorTest.php
@@ -59,7 +59,6 @@ class ComposerSettingsValidatorTest extends PackageManagerKernelTestBase {
    * @dataProvider providerSecureHttpValidation
    */
   public function testSecureHttpValidation(string $contents, array $expected_results): void {
-    $this->createTestProject();
     $active_dir = $this->container->get('package_manager.path_locator')
       ->getProjectRoot();
     file_put_contents("$active_dir/composer.json", $contents);
diff --git a/package_manager/tests/src/Kernel/DiskSpaceValidatorTest.php b/package_manager/tests/src/Kernel/DiskSpaceValidatorTest.php
index a972c7e8a4..c18c5e440f 100644
--- a/package_manager/tests/src/Kernel/DiskSpaceValidatorTest.php
+++ b/package_manager/tests/src/Kernel/DiskSpaceValidatorTest.php
@@ -20,7 +20,7 @@ class DiskSpaceValidatorTest extends PackageManagerKernelTestBase {
    *   Sets of arguments to pass to the test method.
    */
   public function providerDiskSpaceValidation(): array {
-    // These will be defined by ::createTestProject().
+    // These are defined by ::createVirtualProject().
     $root = 'vfs://root/active';
     $vendor = "$root/vendor";
 
@@ -143,8 +143,6 @@ class DiskSpaceValidatorTest extends PackageManagerKernelTestBase {
    * @dataProvider providerDiskSpaceValidation
    */
   public function testDiskSpaceValidation(bool $shared_disk, array $free_space, array $expected_results): void {
-    $this->createTestProject();
-
     /** @var \Drupal\Tests\package_manager\Kernel\TestDiskSpaceValidator $validator */
     $validator = $this->container->get('package_manager.validator.disk_space');
     $validator->sharedDisk = $shared_disk;
diff --git a/package_manager/tests/src/Kernel/LockFileValidatorTest.php b/package_manager/tests/src/Kernel/LockFileValidatorTest.php
index 0d3e5c6af6..803ca066ab 100644
--- a/package_manager/tests/src/Kernel/LockFileValidatorTest.php
+++ b/package_manager/tests/src/Kernel/LockFileValidatorTest.php
@@ -28,7 +28,6 @@ class LockFileValidatorTest extends PackageManagerKernelTestBase {
    */
   protected function setUp(): void {
     parent::setUp();
-    $this->createTestProject();
     $this->activeDir = $this->container->get('package_manager.path_locator')
       ->getProjectRoot();
   }
diff --git a/package_manager/tests/src/Kernel/MultisiteValidatorTest.php b/package_manager/tests/src/Kernel/MultisiteValidatorTest.php
index b83fe43af3..a21f5c0229 100644
--- a/package_manager/tests/src/Kernel/MultisiteValidatorTest.php
+++ b/package_manager/tests/src/Kernel/MultisiteValidatorTest.php
@@ -46,8 +46,6 @@ class MultisiteValidatorTest extends PackageManagerKernelTestBase {
    * @dataProvider providerMultisite
    */
   public function testMultisite(bool $is_multisite, array $expected_results = []): void {
-    $this->createTestProject();
-
     // If we should simulate a multisite, ensure there is a sites.php in the
     // test project.
     // @see \Drupal\package_manager\Validator\MultisiteValidator::isMultisite()
diff --git a/package_manager/tests/src/Kernel/PackageManagerKernelTestBase.php b/package_manager/tests/src/Kernel/PackageManagerKernelTestBase.php
index 617d068d17..3d42bf13bb 100644
--- a/package_manager/tests/src/Kernel/PackageManagerKernelTestBase.php
+++ b/package_manager/tests/src/Kernel/PackageManagerKernelTestBase.php
@@ -53,15 +53,7 @@ abstract class PackageManagerKernelTestBase extends KernelTestBase {
    *
    * @var string[]
    */
-  protected $disableValidators = [
-    // Disable the filesystem permissions validator, since we cannot guarantee
-    // that the current code base will be writable in all testing situations.
-    // We test this validator functionally in Automatic Updates' build tests,
-    // since those do give us control over the filesystem permissions.
-    // @see \Drupal\Tests\automatic_updates\Build\CoreUpdateTest::assertReadOnlyFileSystemError()
-    // @see \Drupal\Tests\package_manager\Kernel\WritableFileSystemValidatorTest
-    'package_manager.validator.file_system',
-  ];
+  protected $disableValidators = [];
 
   /**
    * {@inheritdoc}
@@ -69,6 +61,8 @@ abstract class PackageManagerKernelTestBase extends KernelTestBase {
   protected function setUp(): void {
     parent::setUp();
     $this->installConfig('package_manager');
+
+    $this->createVirtualProject();
   }
 
   /**
@@ -89,7 +83,7 @@ abstract class PackageManagerKernelTestBase extends KernelTestBase {
     // is rebuilt, which destroys the mocked services and can cause unexpected
     // side effects. The 'persist' tag prevents the mocks from being destroyed
     // during a container rebuild.
-    // @see ::createTestProject()
+    // @see ::createVirtualProject()
     $persist = [
       'package_manager.path_locator',
       'package_manager.validator.disk_space',
@@ -181,7 +175,7 @@ abstract class PackageManagerKernelTestBase extends KernelTestBase {
    * and 'stage', which is the root directory used to stage changes. The path
    * locator service will also be mocked so that it points to the test project.
    */
-  protected function createTestProject(): void {
+  protected function createVirtualProject(): void {
     // Create the active directory and copy its contents from a fixture.
     $active_dir = vfsStream::newDirectory('active');
     $this->vfsRoot->addChild($active_dir);
diff --git a/package_manager/tests/src/Kernel/PathExcluder/GitExcluderTest.php b/package_manager/tests/src/Kernel/PathExcluder/GitExcluderTest.php
index a1817cc0d0..24ca0cb409 100644
--- a/package_manager/tests/src/Kernel/PathExcluder/GitExcluderTest.php
+++ b/package_manager/tests/src/Kernel/PathExcluder/GitExcluderTest.php
@@ -26,7 +26,6 @@ class GitExcluderTest extends PackageManagerKernelTestBase {
    * Tests that unreadable directories are ignored by the event subscriber.
    */
   public function testUnreadableDirectoriesAreIgnored(): void {
-    $this->createTestProject();
     $active_dir = $this->container->get('package_manager.path_locator')
       ->getProjectRoot();
 
@@ -51,7 +50,6 @@ class GitExcluderTest extends PackageManagerKernelTestBase {
     // Ensure we have an up-to-date container.
     $this->container = $this->container->get('kernel')->getContainer();
 
-    $this->createTestProject();
     $active_dir = $this->container->get('package_manager.path_locator')
       ->getProjectRoot();
 
diff --git a/package_manager/tests/src/Kernel/PathExcluder/SiteConfigurationExcluderTest.php b/package_manager/tests/src/Kernel/PathExcluder/SiteConfigurationExcluderTest.php
index 95c4352e4c..75f0b0cd3f 100644
--- a/package_manager/tests/src/Kernel/PathExcluder/SiteConfigurationExcluderTest.php
+++ b/package_manager/tests/src/Kernel/PathExcluder/SiteConfigurationExcluderTest.php
@@ -44,7 +44,6 @@ class SiteConfigurationExcluderTest extends PackageManagerKernelTestBase {
     // Ensure we have an up-to-date container.
     $this->container = $this->container->get('kernel')->getContainer();
 
-    $this->createTestProject();
     $active_dir = $this->container->get('package_manager.path_locator')
       ->getProjectRoot();
 
diff --git a/package_manager/tests/src/Kernel/PathExcluder/SiteFilesExcluderTest.php b/package_manager/tests/src/Kernel/PathExcluder/SiteFilesExcluderTest.php
index 5241397642..3dd86484ae 100644
--- a/package_manager/tests/src/Kernel/PathExcluder/SiteFilesExcluderTest.php
+++ b/package_manager/tests/src/Kernel/PathExcluder/SiteFilesExcluderTest.php
@@ -36,7 +36,6 @@ class SiteFilesExcluderTest extends PackageManagerKernelTestBase {
     // Ensure we have an up-to-date container.
     $this->container = $this->container->get('kernel')->getContainer();
 
-    $this->createTestProject();
     $active_dir = $this->container->get('package_manager.path_locator')
       ->getProjectRoot();
 
diff --git a/package_manager/tests/src/Kernel/PathExcluder/SqliteDatabaseExcluderTest.php b/package_manager/tests/src/Kernel/PathExcluder/SqliteDatabaseExcluderTest.php
index 9671134607..dc8350b56a 100644
--- a/package_manager/tests/src/Kernel/PathExcluder/SqliteDatabaseExcluderTest.php
+++ b/package_manager/tests/src/Kernel/PathExcluder/SqliteDatabaseExcluderTest.php
@@ -61,7 +61,6 @@ class SqliteDatabaseExcluderTest extends PackageManagerKernelTestBase {
     // Ensure we have an up-to-date container.
     $this->container = $this->container->get('kernel')->getContainer();
 
-    $this->createTestProject();
     $active_dir = $this->container->get('package_manager.path_locator')
       ->getProjectRoot();
 
@@ -99,8 +98,6 @@ class SqliteDatabaseExcluderTest extends PackageManagerKernelTestBase {
    *   Sets of arguments to pass to the test method.
    */
   public function providerPathProcessing(): array {
-    $drupal_root = $this->getDrupalRoot();
-
     return [
       'relative path, in site directory' => [
         'sites/example.com/db.sqlite',
@@ -119,7 +116,7 @@ class SqliteDatabaseExcluderTest extends PackageManagerKernelTestBase {
         ],
       ],
       'absolute path, in site directory' => [
-        $drupal_root . '/sites/example.com/db.sqlite',
+        '/sites/example.com/db.sqlite',
         [
           'sites/example.com/db.sqlite',
           'sites/example.com/db.sqlite-shm',
@@ -127,7 +124,7 @@ class SqliteDatabaseExcluderTest extends PackageManagerKernelTestBase {
         ],
       ],
       'absolute path, at root' => [
-        $drupal_root . '/db.sqlite',
+        '/db.sqlite',
         [
           'db.sqlite',
           'db.sqlite-shm',
@@ -146,13 +143,19 @@ class SqliteDatabaseExcluderTest extends PackageManagerKernelTestBase {
    *
    * @param string $database_path
    *   The path of the SQLite database, as set in the database connection
-   *   options.
+   *   options. If it begins with a slash, it will be prefixed with the path of
+   *   the active directory.
    * @param string[] $expected_exclusions
    *   The database paths which should be flagged for exclusion.
    *
    * @dataProvider providerPathProcessing
    */
   public function testPathProcessing(string $database_path, array $expected_exclusions): void {
+    // If the database path should be treated as absolute, prefix it with the
+    // path of the active directory.
+    if (str_starts_with($database_path, '/')) {
+      $database_path = $this->container->get('package_manager.path_locator')->getProjectRoot() . $database_path;
+    }
     $this->mockDatabase([
       'database' => $database_path,
     ]);
diff --git a/package_manager/tests/src/Kernel/PathExcluder/TestSiteExcluderTest.php b/package_manager/tests/src/Kernel/PathExcluder/TestSiteExcluderTest.php
index 7b19c31732..43a7ad9f06 100644
--- a/package_manager/tests/src/Kernel/PathExcluder/TestSiteExcluderTest.php
+++ b/package_manager/tests/src/Kernel/PathExcluder/TestSiteExcluderTest.php
@@ -32,7 +32,6 @@ class TestSiteExcluderTest extends PackageManagerKernelTestBase {
     // Ensure we have an up-to-date container.
     $this->container = $this->container->get('kernel')->getContainer();
 
-    $this->createTestProject();
     $active_dir = $this->container->get('package_manager.path_locator')
       ->getProjectRoot();
 
diff --git a/package_manager/tests/src/Kernel/PathExcluder/VendorHardeningExcluderTest.php b/package_manager/tests/src/Kernel/PathExcluder/VendorHardeningExcluderTest.php
index 8d74f74daa..0e28251ea7 100644
--- a/package_manager/tests/src/Kernel/PathExcluder/VendorHardeningExcluderTest.php
+++ b/package_manager/tests/src/Kernel/PathExcluder/VendorHardeningExcluderTest.php
@@ -32,7 +32,6 @@ class VendorHardeningExcluderTest extends PackageManagerKernelTestBase {
     // Ensure we have an up-to-date container.
     $this->container = $this->container->get('kernel')->getContainer();
 
-    $this->createTestProject();
     $active_dir = $this->container->get('package_manager.path_locator')
       ->getProjectRoot();
 
diff --git a/package_manager/tests/src/Kernel/PendingUpdatesValidatorTest.php b/package_manager/tests/src/Kernel/PendingUpdatesValidatorTest.php
index 80a3640bb2..35605045ea 100644
--- a/package_manager/tests/src/Kernel/PendingUpdatesValidatorTest.php
+++ b/package_manager/tests/src/Kernel/PendingUpdatesValidatorTest.php
@@ -17,16 +17,6 @@ class PendingUpdatesValidatorTest extends PackageManagerKernelTestBase {
    */
   protected static $modules = ['system'];
 
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp(): void {
-    parent::setUp();
-    // Use a virtual project so that the test isn't affected by symlinks or
-    // other unexpected things that might be present in the running code base.
-    $this->createTestProject();
-  }
-
   /**
    * Tests that no error is raised if there are no pending updates.
    */
diff --git a/package_manager/tests/src/Kernel/SettingsValidatorTest.php b/package_manager/tests/src/Kernel/SettingsValidatorTest.php
index 5a1633a884..f319740eaf 100644
--- a/package_manager/tests/src/Kernel/SettingsValidatorTest.php
+++ b/package_manager/tests/src/Kernel/SettingsValidatorTest.php
@@ -38,10 +38,6 @@ class SettingsValidatorTest extends PackageManagerKernelTestBase {
    * @dataProvider providerSettingsValidation
    */
   public function testSettingsValidation(bool $setting, array $expected_results): void {
-    // Use a virtual project so that the test isn't affected by symlinks or
-    // other unexpected things that might be present in the running code base.
-    $this->createTestProject();
-
     $this->setSetting('update_fetch_with_http_fallback', $setting);
 
     try {
diff --git a/package_manager/tests/src/Kernel/StageEventsTest.php b/package_manager/tests/src/Kernel/StageEventsTest.php
index 877dfa71ff..4ea2817c1f 100644
--- a/package_manager/tests/src/Kernel/StageEventsTest.php
+++ b/package_manager/tests/src/Kernel/StageEventsTest.php
@@ -44,9 +44,6 @@ class StageEventsTest extends PackageManagerKernelTestBase implements EventSubsc
    */
   protected function setUp(): void {
     parent::setUp();
-    // Use a virtual project so that the test isn't affected by symlinks or
-    // other unexpected things that might be present in the running code base.
-    $this->createTestProject();
     $this->stage = $this->createStage();
   }
 
diff --git a/package_manager/tests/src/Kernel/StageOwnershipTest.php b/package_manager/tests/src/Kernel/StageOwnershipTest.php
index bcfe025be7..21011a7578 100644
--- a/package_manager/tests/src/Kernel/StageOwnershipTest.php
+++ b/package_manager/tests/src/Kernel/StageOwnershipTest.php
@@ -39,9 +39,6 @@ class StageOwnershipTest extends PackageManagerKernelTestBase {
     $this->installSchema('user', ['users_data']);
     $this->installEntitySchema('user');
     $this->registerPostUpdateFunctions();
-    // Use a virtual project so that the test isn't affected by symlinks or
-    // other unexpected things that might be present in the running code base.
-    $this->createTestProject();
   }
 
   /**
@@ -242,7 +239,6 @@ class StageOwnershipTest extends PackageManagerKernelTestBase {
     ]);
     // Ensure we have an up-to-date container.
     $this->container = $this->container->get('kernel')->getContainer();
-    $this->createTestProject();
 
     $logger_channel = $this->container->get('logger.channel.file');
     $arguments = [
diff --git a/package_manager/tests/src/Kernel/StageTest.php b/package_manager/tests/src/Kernel/StageTest.php
index addfa40f70..76c5d8a86c 100644
--- a/package_manager/tests/src/Kernel/StageTest.php
+++ b/package_manager/tests/src/Kernel/StageTest.php
@@ -67,6 +67,10 @@ class StageTest extends PackageManagerKernelTestBase {
     $site_id = $this->config('system.site')->get('uuid');
     $this->assertNotEmpty($site_id);
 
+    // Even though we're using a virtual project, we want to test what happens
+    // when we aren't.
+    static::$testStagingRoot = NULL;
+
     $stage = $this->createStage();
     $id = $stage->create();
     // If the file_temp_path setting is empty, the stage directory should be
diff --git a/package_manager/tests/src/Kernel/SymlinkValidatorTest.php b/package_manager/tests/src/Kernel/SymlinkValidatorTest.php
index ea93febb6e..5e462dd444 100644
--- a/package_manager/tests/src/Kernel/SymlinkValidatorTest.php
+++ b/package_manager/tests/src/Kernel/SymlinkValidatorTest.php
@@ -14,14 +14,6 @@ use Drupal\package_manager\Validator\SymlinkValidator;
  */
 class SymlinkValidatorTest extends PackageManagerKernelTestBase {
 
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp(): void {
-    parent::setUp();
-    $this->createTestProject();
-  }
-
   /**
    * {@inheritdoc}
    */
@@ -66,7 +58,7 @@ class SymlinkValidatorTest extends PackageManagerKernelTestBase {
     $stage->create();
     // Simulate updating a package. This will copy the active directory into
     // the (virtual) staging area.
-    // @see ::createTestProject()
+    // @see ::createVirtualProject()
     // @see \Drupal\package_manager_test_fixture\EventSubscriber\FixtureStager::copyFilesFromFixture()
     $stage->require(['composer/semver:^3']);
 
@@ -99,7 +91,7 @@ class SymlinkValidatorTest extends PackageManagerKernelTestBase {
     $stage->create();
     // Simulate updating a package. This will copy the active directory into
     // the (virtual) staging area.
-    // @see ::createTestProject()
+    // @see ::createVirtualProject()
     // @see \Drupal\package_manager_test_fixture\EventSubscriber\FixtureStager::copyFilesFromFixture()
     $stage->require(['composer/semver:^3']);
 
diff --git a/package_manager/tests/src/Kernel/WritableFileSystemValidatorTest.php b/package_manager/tests/src/Kernel/WritableFileSystemValidatorTest.php
index addf0a2172..411c27b4c5 100644
--- a/package_manager/tests/src/Kernel/WritableFileSystemValidatorTest.php
+++ b/package_manager/tests/src/Kernel/WritableFileSystemValidatorTest.php
@@ -3,9 +3,7 @@
 namespace Drupal\Tests\package_manager\Kernel;
 
 use Drupal\package_manager\Event\PreCreateEvent;
-use Drupal\package_manager\Validator\WritableFileSystemValidator;
 use Drupal\package_manager\ValidationResult;
-use Drupal\Core\DependencyInjection\ContainerBuilder;
 
 /**
  * Unit tests the file system permissions validator.
@@ -21,26 +19,6 @@ use Drupal\Core\DependencyInjection\ContainerBuilder;
  */
 class WritableFileSystemValidatorTest extends PackageManagerKernelTestBase {
 
-  /**
-   * {@inheritdoc}
-   */
-  protected $disableValidators = [
-    // The parent class disables the validator we're testing, so prevent that
-    // here with an empty array.
-  ];
-
-  /**
-   * {@inheritdoc}
-   */
-  public function register(ContainerBuilder $container) {
-    parent::register($container);
-
-    // Replace the file system permissions validator with our test-only
-    // implementation.
-    $container->getDefinition('package_manager.validator.file_system')
-      ->setClass(TestWritableFileSystemValidator::class);
-  }
-
   /**
    * Data provider for ::testWritable().
    *
@@ -48,7 +26,7 @@ class WritableFileSystemValidatorTest extends PackageManagerKernelTestBase {
    *   Sets of arguments to pass to the test method.
    */
   public function providerWritable(): array {
-    // The root and vendor paths are defined by ::createTestProject().
+    // The root and vendor paths are defined by ::createVirtualProject().
     $root_error = 'The Drupal directory "vfs://root/active" is not writable.';
     $vendor_error = 'The vendor directory "vfs://root/active/vendor" is not writable.';
     $summary = t('The file system is not writable.');
@@ -98,30 +76,14 @@ class WritableFileSystemValidatorTest extends PackageManagerKernelTestBase {
    * @dataProvider providerWritable
    */
   public function testWritable(int $root_permissions, int $vendor_permissions, array $expected_results): void {
-    $this->createTestProject();
-    // For reasons unclear, the built-in chmod() function doesn't seem to work
-    // when changing vendor permissions, so just call vfsStream's API directly.
-    $active_dir = $this->vfsRoot->getChild('active');
-    $active_dir->chmod($root_permissions);
-    $active_dir->getChild('vendor')->chmod($vendor_permissions);
+    $path_locator = $this->container->get('package_manager.path_locator');
 
-    /** @var \Drupal\Tests\package_manager\Kernel\TestWritableFileSystemValidator $validator */
-    $validator = $this->container->get('package_manager.validator.file_system');
-    $validator->appRoot = $active_dir->url();
+    // We need to set the vendor directory's permissions first because, in the
+    // virtual project, it's located inside the project root.
+    $this->assertTrue(chmod($path_locator->getVendorDirectory(), $vendor_permissions));
+    $this->assertTrue(chmod($path_locator->getProjectRoot(), $root_permissions));
 
     $this->assertResults($expected_results, PreCreateEvent::class);
   }
 
 }
-
-/**
- * A test version of the file system permissions validator.
- */
-class TestWritableFileSystemValidator extends WritableFileSystemValidator {
-
-  /**
-   * {@inheritdoc}
-   */
-  public $appRoot;
-
-}
diff --git a/tests/src/Kernel/CronUpdaterTest.php b/tests/src/Kernel/CronUpdaterTest.php
index f07e16086f..115f024f87 100644
--- a/tests/src/Kernel/CronUpdaterTest.php
+++ b/tests/src/Kernel/CronUpdaterTest.php
@@ -357,10 +357,6 @@ class CronUpdaterTest extends AutomaticUpdatesKernelTestBase {
    * Tests that user 1 is emailed when an unattended update succeeds.
    */
   public function testEmailOnSuccess(): void {
-    // Use a virtual project so that the test is unaffected by symlinks or other
-    // artifacts that might be in the running code base.
-    $this->createTestProject();
-
     $this->config('update.settings')
       ->set('notification.emails', [
         'emissary@deep.space',
diff --git a/tests/src/Kernel/ReadinessValidation/CronFrequencyValidatorTest.php b/tests/src/Kernel/ReadinessValidation/CronFrequencyValidatorTest.php
index 75fb7ee57f..601da39fa4 100644
--- a/tests/src/Kernel/ReadinessValidation/CronFrequencyValidatorTest.php
+++ b/tests/src/Kernel/ReadinessValidation/CronFrequencyValidatorTest.php
@@ -26,10 +26,6 @@ class CronFrequencyValidatorTest extends AutomaticUpdatesKernelTestBase {
    */
   protected function setUp(): void {
     parent::setUp();
-    // Run with a virtual project so that the test isn't affected by any
-    // symbolic links or other artifacts that might be in the running code
-    // base.
-    $this->createTestProject();
     // In this test, we do not want to do an update. We're just testing that
     // cron is configured to run frequently enough to do automatic updates. So,
     // pretend we're already on the latest secure version of core.
diff --git a/tests/src/Kernel/ReadinessValidation/ReadinessValidationManagerTest.php b/tests/src/Kernel/ReadinessValidation/ReadinessValidationManagerTest.php
index d9fb9faf80..7766e911d7 100644
--- a/tests/src/Kernel/ReadinessValidation/ReadinessValidationManagerTest.php
+++ b/tests/src/Kernel/ReadinessValidation/ReadinessValidationManagerTest.php
@@ -34,9 +34,6 @@ class ReadinessValidationManagerTest extends AutomaticUpdatesKernelTestBase {
     $this->installEntitySchema('user');
     $this->installSchema('user', ['users_data']);
     $this->createTestValidationResults();
-    // Use a virtual project so that the test isn't affected by symlinks or
-    // other unexpected things that might be present in the running code base.
-    $this->createTestProject();
   }
 
   /**
diff --git a/tests/src/Kernel/ReadinessValidation/ScaffoldFilePermissionsValidatorTest.php b/tests/src/Kernel/ReadinessValidation/ScaffoldFilePermissionsValidatorTest.php
index d77ce05b3a..8f4e0530c8 100644
--- a/tests/src/Kernel/ReadinessValidation/ScaffoldFilePermissionsValidatorTest.php
+++ b/tests/src/Kernel/ReadinessValidation/ScaffoldFilePermissionsValidatorTest.php
@@ -31,7 +31,6 @@ class ScaffoldFilePermissionsValidatorTest extends AutomaticUpdatesKernelTestBas
   protected function setUp(): void {
     parent::setUp();
 
-    $this->createTestProject();
     $this->activeDir = $this->container->get('package_manager.path_locator')
       ->getProjectRoot();
   }
@@ -299,7 +298,7 @@ class ScaffoldFilePermissionsValidatorTest extends AutomaticUpdatesKernelTestBas
 
     // Simulate updating Drupal core. This will copy the active directory into
     // the (virtual) staging area.
-    // @see ::createTestProject()
+    // @see ::createVirtualProject()
     // @see \Drupal\package_manager_test_fixture\EventSubscriber\FixtureStager::copyFilesFromFixture()
     $updater = $this->container->get('automatic_updates.updater');
     $updater->begin(['drupal' => '9.8.1']);
diff --git a/tests/src/Kernel/ReadinessValidation/StagedDatabaseUpdateValidatorTest.php b/tests/src/Kernel/ReadinessValidation/StagedDatabaseUpdateValidatorTest.php
index 086575a13c..e06b324f3f 100644
--- a/tests/src/Kernel/ReadinessValidation/StagedDatabaseUpdateValidatorTest.php
+++ b/tests/src/Kernel/ReadinessValidation/StagedDatabaseUpdateValidatorTest.php
@@ -38,7 +38,6 @@ class StagedDatabaseUpdateValidatorTest extends AutomaticUpdatesKernelTestBase {
    */
   protected function setUp(): void {
     parent::setUp();
-    $this->createTestProject();
 
     $this->logger = new TestLogger();
     $this->container->get('logger.factory')
@@ -49,8 +48,8 @@ class StagedDatabaseUpdateValidatorTest extends AutomaticUpdatesKernelTestBase {
   /**
    * {@inheritdoc}
    */
-  protected function createTestProject(): void {
-    parent::createTestProject();
+  protected function createVirtualProject(): void {
+    parent::createVirtualProject();
 
     $drupal_root = $this->getDrupalRoot();
     $virtual_active_dir = $this->container->get('package_manager.path_locator')
diff --git a/tests/src/Kernel/ReadinessValidation/StagedProjectsValidatorTest.php b/tests/src/Kernel/ReadinessValidation/StagedProjectsValidatorTest.php
index 7268428389..924772eb17 100644
--- a/tests/src/Kernel/ReadinessValidation/StagedProjectsValidatorTest.php
+++ b/tests/src/Kernel/ReadinessValidation/StagedProjectsValidatorTest.php
@@ -32,7 +32,6 @@ class StagedProjectsValidatorTest extends AutomaticUpdatesKernelTestBase {
   protected function setUp(): void {
     parent::setUp();
 
-    $this->createTestProject();
     $this->activeDir = $this->container->get('package_manager.path_locator')
       ->getProjectRoot();
   }
diff --git a/tests/src/Kernel/ReadinessValidation/VersionPolicyValidatorTest.php b/tests/src/Kernel/ReadinessValidation/VersionPolicyValidatorTest.php
index 4363bfb475..599f04e8af 100644
--- a/tests/src/Kernel/ReadinessValidation/VersionPolicyValidatorTest.php
+++ b/tests/src/Kernel/ReadinessValidation/VersionPolicyValidatorTest.php
@@ -21,16 +21,6 @@ class VersionPolicyValidatorTest extends AutomaticUpdatesKernelTestBase {
    */
   protected static $modules = ['automatic_updates'];
 
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp(): void {
-    parent::setUp();
-    // Use a virtual project so that the test isn't affected by symlinks or
-    // other unexpected things that might be present in the running code base.
-    $this->createTestProject();
-  }
-
   /**
    * Data provider for ::testReadinessCheck().
    *
@@ -413,7 +403,6 @@ class VersionPolicyValidatorTest extends AutomaticUpdatesKernelTestBase {
    *   known.
    */
   private function assertTargetVersionNotDiscoverable(\Closure $listener): void {
-    $this->createTestProject();
     $this->container->get('event_dispatcher')
       ->addListener(PreCreateEvent::class, $listener, PHP_INT_MAX);
 
-- 
GitLab