Skip to content
Snippets Groups Projects
Commit d8384b58 authored by Adam G-H's avatar Adam G-H Committed by Ted Bowman
Browse files

Issue #3230510 by phenaproxima, tedbow: Turn ExclusionsTest into a functional test

parent fcbb50e6
No related branches found
No related tags found
No related merge requests found
Showing
with 151 additions and 49 deletions
...@@ -72,6 +72,6 @@ services: ...@@ -72,6 +72,6 @@ services:
class: Drupal\automatic_updates\ComposerStager\ProcessFactory class: Drupal\automatic_updates\ComposerStager\ProcessFactory
automatic_updates.excluded_paths_subscriber: automatic_updates.excluded_paths_subscriber:
class: Drupal\automatic_updates\Event\ExcludedPathsSubscriber class: Drupal\automatic_updates\Event\ExcludedPathsSubscriber
arguments: ['%app.root%', '%site.path%', '@file_system'] arguments: ['%app.root%', '%site.path%', '@file_system', '@stream_wrapper_manager']
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
...@@ -4,6 +4,8 @@ namespace Drupal\automatic_updates\Event; ...@@ -4,6 +4,8 @@ namespace Drupal\automatic_updates\Event;
use Drupal\automatic_updates\AutomaticUpdatesEvents; use Drupal\automatic_updates\AutomaticUpdatesEvents;
use Drupal\Core\File\FileSystemInterface; use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\StreamWrapper\LocalStream;
use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/** /**
...@@ -32,6 +34,13 @@ class ExcludedPathsSubscriber implements EventSubscriberInterface { ...@@ -32,6 +34,13 @@ class ExcludedPathsSubscriber implements EventSubscriberInterface {
*/ */
protected $fileSystem; protected $fileSystem;
/**
* The stream wrapper manager service.
*
* @var \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface
*/
protected $streamWrapperManager;
/** /**
* Constructs an UpdateSubscriber. * Constructs an UpdateSubscriber.
* *
...@@ -41,11 +50,14 @@ class ExcludedPathsSubscriber implements EventSubscriberInterface { ...@@ -41,11 +50,14 @@ class ExcludedPathsSubscriber implements EventSubscriberInterface {
* The current site path, relative to the Drupal root. * The current site path, relative to the Drupal root.
* @param \Drupal\Core\File\FileSystemInterface $file_system * @param \Drupal\Core\File\FileSystemInterface $file_system
* The file system service. * 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->appRoot = $app_root;
$this->sitePath = $site_path; $this->sitePath = $site_path;
$this->fileSystem = $file_system; $this->fileSystem = $file_system;
$this->streamWrapperManager = $stream_wrapper_manager;
} }
/** /**
...@@ -55,10 +67,13 @@ class ExcludedPathsSubscriber implements EventSubscriberInterface { ...@@ -55,10 +67,13 @@ class ExcludedPathsSubscriber implements EventSubscriberInterface {
* The event object. * The event object.
*/ */
public function preStart(PreStartEvent $event): void { 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); $event->excludePath($public);
} }
if ($private = $this->fileSystem->realpath('private://')) { if ($private = $this->getFilesPath('private')) {
$event->excludePath($private); $event->excludePath($private);
} }
// If this module is a git clone, exclude it. // If this module is a git clone, exclude it.
...@@ -92,6 +107,29 @@ class ExcludedPathsSubscriber implements EventSubscriberInterface { ...@@ -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} * {@inheritdoc}
*/ */
......
This private file should never be staged.
This public file should never be staged.
This file should be staged.
# A fake services file that should never be staged.
services: {}
<?php
/**
* @file
* A fake local settings file that should never be staged.
*/
<?php
/**
* @file
* A fake settings file that should never be staged.
*/
This file should be staged.
This file should not be staged.
<?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);
}
}
}
<?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();
}
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
namespace Drupal\Tests\automatic_updates\Functional; namespace Drupal\Tests\automatic_updates\Functional;
use Drupal\automatic_updates\Event\PreStartEvent; use Drupal\Core\Site\Settings;
use Drupal\Tests\BrowserTestBase; use Drupal\Tests\BrowserTestBase;
/** /**
...@@ -15,64 +15,44 @@ class ExclusionsTest extends BrowserTestBase { ...@@ -15,64 +15,44 @@ class ExclusionsTest extends BrowserTestBase {
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
protected static $modules = ['automatic_updates']; protected static $modules = ['automatic_updates_test'];
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
protected $defaultTheme = 'stark'; 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. * Tests that certain files and directories are not staged.
* *
* @covers \Drupal\automatic_updates\Updater::getExclusions * @covers \Drupal\automatic_updates\Updater::getExclusions
*/ */
public function testExclusions(): void { public function testExclusions(): void {
$event = new PreStartEvent(); $stage_dir = "$this->siteDirectory/stage";
$this->container->get('automatic_updates.excluded_paths_subscriber')
->preStart($event);
/** @var \Drupal\automatic_updates\Updater $updater */ /** @var \Drupal\automatic_updates_test\TestUpdater $updater */
$updater = $this->container->get('automatic_updates.updater'); $updater = $this->container->get('automatic_updates.updater');
$reflector = new \ReflectionObject($updater); $updater->activeDirectory = __DIR__ . '/../../fixtures/fake-site';
$method = $reflector->getMethod('getExclusions'); $updater->stageDirectory = $stage_dir;
$method->setAccessible(TRUE);
$exclusions = $method->invoke($updater, $event); $settings = Settings::getAll();
$settings['file_public_path'] = 'files/public';
$this->assertContains("$this->siteDirectory/files", $exclusions); $settings['file_private_path'] = 'files/private';
$this->assertContains("$this->siteDirectory/private", $exclusions); new Settings($settings);
foreach (static::SETTINGS_FILES as $settings_file) {
$this->assertContains("$this->siteDirectory/$settings_file", $exclusions); $updater->begin();
} $this->assertFileDoesNotExist("$stage_dir/sites/default/settings.php");
if (is_dir(__DIR__ . '/../../../.git')) { $this->assertFileDoesNotExist("$stage_dir/sites/default/settings.local.php");
$module_path = $this->container->get('extension.list.module') $this->assertFileDoesNotExist("$stage_dir/sites/default/services.yml");
->getPath('automatic_updates'); // A file in sites/default, that isn't one of the site-specific settings
$this->assertContains($module_path, $exclusions); // 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");
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment