From d8384b58dad8bb152957d1d6fbc242a9f6930b0b Mon Sep 17 00:00:00 2001 From: phenaproxima <phenaproxima@205645.no-reply.drupal.org> Date: Tue, 31 Aug 2021 18:06:00 +0000 Subject: [PATCH] Issue #3230510 by phenaproxima, tedbow: Turn ExclusionsTest into a functional test --- automatic_updates.services.yml | 2 +- src/Event/ExcludedPathsSubscriber.php | 44 +++++++++++- .../fake-site/files/private/ignore.txt | 1 + .../fake-site/files/public/ignore.txt | 1 + tests/fixtures/fake-site/files/staged.txt | 1 + .../fake-site/sites/default/services.yml | 2 + .../sites/default/settings.local.php | 6 ++ .../fake-site/sites/default/settings.php | 6 ++ .../fake-site/sites/default/staged.txt | 1 + .../fake-site/sites/simpletest/ignore.txt | 1 + .../AutomaticUpdatesTestServiceProvider.php | 25 +++++++ .../src/TestUpdater.php | 40 +++++++++++ tests/src/Functional/ExclusionsTest.php | 70 +++++++------------ 13 files changed, 151 insertions(+), 49 deletions(-) create mode 100644 tests/fixtures/fake-site/files/private/ignore.txt create mode 100644 tests/fixtures/fake-site/files/public/ignore.txt create mode 100644 tests/fixtures/fake-site/files/staged.txt create mode 100644 tests/fixtures/fake-site/sites/default/services.yml create mode 100644 tests/fixtures/fake-site/sites/default/settings.local.php create mode 100644 tests/fixtures/fake-site/sites/default/settings.php create mode 100644 tests/fixtures/fake-site/sites/default/staged.txt create mode 100644 tests/fixtures/fake-site/sites/simpletest/ignore.txt create mode 100644 tests/modules/automatic_updates_test/src/AutomaticUpdatesTestServiceProvider.php create mode 100644 tests/modules/automatic_updates_test/src/TestUpdater.php diff --git a/automatic_updates.services.yml b/automatic_updates.services.yml index 2b05d22d68..575eff1a4d 100644 --- a/automatic_updates.services.yml +++ b/automatic_updates.services.yml @@ -72,6 +72,6 @@ services: class: Drupal\automatic_updates\ComposerStager\ProcessFactory automatic_updates.excluded_paths_subscriber: class: Drupal\automatic_updates\Event\ExcludedPathsSubscriber - arguments: ['%app.root%', '%site.path%', '@file_system'] + arguments: ['%app.root%', '%site.path%', '@file_system', '@stream_wrapper_manager'] tags: - { name: event_subscriber } diff --git a/src/Event/ExcludedPathsSubscriber.php b/src/Event/ExcludedPathsSubscriber.php index 6665a5378d..f9d46efa45 100644 --- a/src/Event/ExcludedPathsSubscriber.php +++ b/src/Event/ExcludedPathsSubscriber.php @@ -4,6 +4,8 @@ namespace Drupal\automatic_updates\Event; use Drupal\automatic_updates\AutomaticUpdatesEvents; use Drupal\Core\File\FileSystemInterface; +use Drupal\Core\StreamWrapper\LocalStream; +use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** @@ -32,6 +34,13 @@ class ExcludedPathsSubscriber implements EventSubscriberInterface { */ protected $fileSystem; + /** + * The stream wrapper manager service. + * + * @var \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface + */ + protected $streamWrapperManager; + /** * Constructs an UpdateSubscriber. * @@ -41,11 +50,14 @@ class ExcludedPathsSubscriber implements EventSubscriberInterface { * The current site path, relative to the Drupal root. * @param \Drupal\Core\File\FileSystemInterface $file_system * The file system service. + * @param \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface $stream_wrapper_manager + * The stream wrapper manager service. */ - public function __construct(string $app_root, string $site_path, FileSystemInterface $file_system) { + public function __construct(string $app_root, string $site_path, FileSystemInterface $file_system, StreamWrapperManagerInterface $stream_wrapper_manager) { $this->appRoot = $app_root; $this->sitePath = $site_path; $this->fileSystem = $file_system; + $this->streamWrapperManager = $stream_wrapper_manager; } /** @@ -55,10 +67,13 @@ class ExcludedPathsSubscriber implements EventSubscriberInterface { * The event object. */ public function preStart(PreStartEvent $event): void { - if ($public = $this->fileSystem->realpath('public://')) { + // Automated test site directories should never be staged. + $event->excludePath('sites/simpletest'); + + if ($public = $this->getFilesPath('public')) { $event->excludePath($public); } - if ($private = $this->fileSystem->realpath('private://')) { + if ($private = $this->getFilesPath('private')) { $event->excludePath($private); } // If this module is a git clone, exclude it. @@ -92,6 +107,29 @@ class ExcludedPathsSubscriber implements EventSubscriberInterface { } } + /** + * Returns the storage path for a stream wrapper. + * + * This will only work for stream wrappers that extend + * \Drupal\Core\StreamWrapper\LocalStream, which includes the stream wrappers + * for public and private files. + * + * @param string $scheme + * The stream wrapper scheme. + * + * @return string|null + * The storage path for files using the given scheme, relative to the Drupal + * root, or NULL if the stream wrapper does not extend + * \Drupal\Core\StreamWrapper\LocalStream. + */ + private function getFilesPath(string $scheme): ?string { + $wrapper = $this->streamWrapperManager->getViaScheme($scheme); + if ($wrapper instanceof LocalStream) { + return $wrapper->getDirectoryPath(); + } + return NULL; + } + /** * {@inheritdoc} */ diff --git a/tests/fixtures/fake-site/files/private/ignore.txt b/tests/fixtures/fake-site/files/private/ignore.txt new file mode 100644 index 0000000000..4f9da38be5 --- /dev/null +++ b/tests/fixtures/fake-site/files/private/ignore.txt @@ -0,0 +1 @@ +This private file should never be staged. diff --git a/tests/fixtures/fake-site/files/public/ignore.txt b/tests/fixtures/fake-site/files/public/ignore.txt new file mode 100644 index 0000000000..ab6a7649fa --- /dev/null +++ b/tests/fixtures/fake-site/files/public/ignore.txt @@ -0,0 +1 @@ +This public file should never be staged. diff --git a/tests/fixtures/fake-site/files/staged.txt b/tests/fixtures/fake-site/files/staged.txt new file mode 100644 index 0000000000..0087269e33 --- /dev/null +++ b/tests/fixtures/fake-site/files/staged.txt @@ -0,0 +1 @@ +This file should be staged. diff --git a/tests/fixtures/fake-site/sites/default/services.yml b/tests/fixtures/fake-site/sites/default/services.yml new file mode 100644 index 0000000000..ea9529af01 --- /dev/null +++ b/tests/fixtures/fake-site/sites/default/services.yml @@ -0,0 +1,2 @@ +# A fake services file that should never be staged. +services: {} diff --git a/tests/fixtures/fake-site/sites/default/settings.local.php b/tests/fixtures/fake-site/sites/default/settings.local.php new file mode 100644 index 0000000000..e54016a9d2 --- /dev/null +++ b/tests/fixtures/fake-site/sites/default/settings.local.php @@ -0,0 +1,6 @@ +<?php + +/** + * @file + * A fake local settings file that should never be staged. + */ diff --git a/tests/fixtures/fake-site/sites/default/settings.php b/tests/fixtures/fake-site/sites/default/settings.php new file mode 100644 index 0000000000..9b995731d1 --- /dev/null +++ b/tests/fixtures/fake-site/sites/default/settings.php @@ -0,0 +1,6 @@ +<?php + +/** + * @file + * A fake settings file that should never be staged. + */ diff --git a/tests/fixtures/fake-site/sites/default/staged.txt b/tests/fixtures/fake-site/sites/default/staged.txt new file mode 100644 index 0000000000..0087269e33 --- /dev/null +++ b/tests/fixtures/fake-site/sites/default/staged.txt @@ -0,0 +1 @@ +This file should be staged. diff --git a/tests/fixtures/fake-site/sites/simpletest/ignore.txt b/tests/fixtures/fake-site/sites/simpletest/ignore.txt new file mode 100644 index 0000000000..e4525907f2 --- /dev/null +++ b/tests/fixtures/fake-site/sites/simpletest/ignore.txt @@ -0,0 +1 @@ +This file should not be staged. diff --git a/tests/modules/automatic_updates_test/src/AutomaticUpdatesTestServiceProvider.php b/tests/modules/automatic_updates_test/src/AutomaticUpdatesTestServiceProvider.php new file mode 100644 index 0000000000..b0bd0924c0 --- /dev/null +++ b/tests/modules/automatic_updates_test/src/AutomaticUpdatesTestServiceProvider.php @@ -0,0 +1,25 @@ +<?php + +namespace Drupal\automatic_updates_test; + +use Drupal\Core\DependencyInjection\ContainerBuilder; +use Drupal\Core\DependencyInjection\ServiceProviderBase; + +/** + * Modifies service definitions for testing purposes. + */ +class AutomaticUpdatesTestServiceProvider extends ServiceProviderBase { + + /** + * {@inheritdoc} + */ + public function alter(ContainerBuilder $container) { + parent::alter($container); + + $service = 'automatic_updates.updater'; + if ($container->hasDefinition($service)) { + $container->getDefinition($service)->setClass(TestUpdater::class); + } + } + +} diff --git a/tests/modules/automatic_updates_test/src/TestUpdater.php b/tests/modules/automatic_updates_test/src/TestUpdater.php new file mode 100644 index 0000000000..aed821d88a --- /dev/null +++ b/tests/modules/automatic_updates_test/src/TestUpdater.php @@ -0,0 +1,40 @@ +<?php + +namespace Drupal\automatic_updates_test; + +use Drupal\automatic_updates\Updater; + +/** + * A testing updater that allows arbitrary active and stage directories. + */ +class TestUpdater extends Updater { + + /** + * The active directory to use, if different from the default. + * + * @var string + */ + public $activeDirectory; + + /** + * The stage directory to use, if different from the default. + * + * @var string + */ + public $stageDirectory; + + /** + * {@inheritdoc} + */ + public function getActiveDirectory(): string { + return $this->activeDirectory ?: parent::getActiveDirectory(); + } + + /** + * {@inheritdoc} + */ + public function getStageDirectory(): string { + return $this->stageDirectory ?: parent::getStageDirectory(); + } + +} diff --git a/tests/src/Functional/ExclusionsTest.php b/tests/src/Functional/ExclusionsTest.php index 5f3f8ede1b..0b978a5c34 100644 --- a/tests/src/Functional/ExclusionsTest.php +++ b/tests/src/Functional/ExclusionsTest.php @@ -2,7 +2,7 @@ namespace Drupal\Tests\automatic_updates\Functional; -use Drupal\automatic_updates\Event\PreStartEvent; +use Drupal\Core\Site\Settings; use Drupal\Tests\BrowserTestBase; /** @@ -15,64 +15,44 @@ class ExclusionsTest extends BrowserTestBase { /** * {@inheritdoc} */ - protected static $modules = ['automatic_updates']; + protected static $modules = ['automatic_updates_test']; /** * {@inheritdoc} */ protected $defaultTheme = 'stark'; - /** - * The names of site-specific settings files to mock. - * - * @var string[] - */ - private const SETTINGS_FILES = [ - 'settings.php', - 'settings.local.php', - 'services.yml', - ]; - - /** - * {@inheritdoc} - */ - protected function setUp(): void { - parent::setUp(); - - foreach (static::SETTINGS_FILES as $settings_file) { - $settings_file = "$this->siteDirectory/$settings_file"; - touch($settings_file); - $this->assertFileExists($settings_file); - } - } - /** * Tests that certain files and directories are not staged. * * @covers \Drupal\automatic_updates\Updater::getExclusions */ public function testExclusions(): void { - $event = new PreStartEvent(); - $this->container->get('automatic_updates.excluded_paths_subscriber') - ->preStart($event); + $stage_dir = "$this->siteDirectory/stage"; - /** @var \Drupal\automatic_updates\Updater $updater */ + /** @var \Drupal\automatic_updates_test\TestUpdater $updater */ $updater = $this->container->get('automatic_updates.updater'); - $reflector = new \ReflectionObject($updater); - $method = $reflector->getMethod('getExclusions'); - $method->setAccessible(TRUE); - $exclusions = $method->invoke($updater, $event); - - $this->assertContains("$this->siteDirectory/files", $exclusions); - $this->assertContains("$this->siteDirectory/private", $exclusions); - foreach (static::SETTINGS_FILES as $settings_file) { - $this->assertContains("$this->siteDirectory/$settings_file", $exclusions); - } - if (is_dir(__DIR__ . '/../../../.git')) { - $module_path = $this->container->get('extension.list.module') - ->getPath('automatic_updates'); - $this->assertContains($module_path, $exclusions); - } + $updater->activeDirectory = __DIR__ . '/../../fixtures/fake-site'; + $updater->stageDirectory = $stage_dir; + + $settings = Settings::getAll(); + $settings['file_public_path'] = 'files/public'; + $settings['file_private_path'] = 'files/private'; + new Settings($settings); + + $updater->begin(); + $this->assertFileDoesNotExist("$stage_dir/sites/default/settings.php"); + $this->assertFileDoesNotExist("$stage_dir/sites/default/settings.local.php"); + $this->assertFileDoesNotExist("$stage_dir/sites/default/services.yml"); + // A file in sites/default, that isn't one of the site-specific settings + // files, should be staged. + $this->assertFileExists("$stage_dir/sites/default/staged.txt"); + $this->assertDirectoryDoesNotExist("$stage_dir/sites/simpletest"); + $this->assertDirectoryDoesNotExist("$stage_dir/files/public"); + $this->assertDirectoryDoesNotExist("$stage_dir/files/private"); + // A file that's in the general files directory, but not in the public or + // private directories, should be staged. + $this->assertFileExists("$stage_dir/files/staged.txt"); } } -- GitLab