Commit f0fda9de authored by catch's avatar catch
Browse files

Issue #3403382 by alexpott, Wim Leers: BuildTestBase makes assumptions it...

Issue #3403382 by alexpott, Wim Leers: BuildTestBase makes assumptions it should not about the code layout

(cherry picked from commit cbbe53da)
parent 6170ea97
Loading
Loading
Loading
Loading
Loading
+56 −8
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
use Behat\Mink\Driver\BrowserKitDriver;
use Behat\Mink\Mink;
use Behat\Mink\Session;
use Composer\InstalledVersions;
use Drupal\Component\FileSystem\FileSystem as DrupalFilesystem;
use Drupal\Tests\DrupalTestBrowser;
use Drupal\Tests\PhpUnitCompatibilityTrait;
@@ -557,7 +558,7 @@ public function copyCodebase(\Iterator $iterator = NULL, $working_dir = NULL) {

    $fs = new SymfonyFilesystem();
    $options = ['override' => TRUE, 'delete' => FALSE];
    $fs->mirror($this->getDrupalRoot(), $working_path, $iterator, $options);
    $fs->mirror($this->getComposerRoot(), $working_path, $iterator, $options);
  }

  /**
@@ -577,14 +578,16 @@ public function copyCodebase(\Iterator $iterator = NULL, $working_dir = NULL) {
   *   A Finder object ready to iterate over core codebase.
   */
  public function getCodebaseFinder() {
    $drupal_root = $this->getWorkingPathDrupalRoot() ?? '';
    $finder = new Finder();
    $finder->files()
      ->followLinks()
      ->ignoreUnreadableDirs()
      ->in($this->getDrupalRoot())
      ->notPath('#^sites/default/files#')
      ->notPath('#^sites/simpletest#')
      ->notPath('#^core/node_modules#')
      ->notPath('#^sites/default/settings\..*php#')
      ->in($this->getComposerRoot())
      ->notPath("#^{$drupal_root}sites/default/files#")
      ->notPath("#^{$drupal_root}sites/simpletest#")
      ->notPath("#^{$drupal_root}core/node_modules#")
      ->notPath("#^{$drupal_root}sites/default/settings\..*php#")
      ->ignoreDotFiles(FALSE)
      ->ignoreVCS(FALSE);
    return $finder;
@@ -596,8 +599,53 @@ public function getCodebaseFinder() {
   * @return string
   *   The full path to the root of this Drupal codebase.
   */
  protected function getDrupalRoot() {
    return realpath(dirname(__DIR__, 5));
  public function getDrupalRoot() {
    // Given this code is in the drupal/core package, $core cannot be NULL.
    /** @var string $core */
    $core = InstalledVersions::getInstallPath('drupal/core');
    return realpath(dirname($core));
  }

  /**
   * Gets the path to the Composer root directory.
   *
   * @return string
   *   The absolute path to the Composer root directory.
   */
  public function getComposerRoot(): string {
    $root = InstalledVersions::getRootPackage();
    return realpath($root['install_path']);
  }

  /**
   * Gets the path to Drupal root in the workspace directory.
   *
   * @return string
   *   The absolute path to the Drupal root directory in the workspace.
   */
  public function getWorkspaceDrupalRoot(): string {
    $dir = $this->getWorkspaceDirectory();
    $drupal_root = $this->getWorkingPathDrupalRoot();
    if ($drupal_root !== NULL) {
      $dir = $dir . DIRECTORY_SEPARATOR . $drupal_root;
    }
    return $dir;
  }

  /**
   * Gets the working path for Drupal core.
   *
   * @return string|null
   *   The relative path to Drupal's root directory or NULL if it is the same
   *   as the composer root directory.
   */
  public function getWorkingPathDrupalRoot(): ?string {
    $composer_root = $this->getComposerRoot();
    $drupal_root = $this->getDrupalRoot();
    if ($composer_root === $drupal_root) {
      return NULL;
    }
    return (new SymfonyFilesystem())->makePathRelative($drupal_root, $composer_root);
  }

}
+85 −3
Original line number Diff line number Diff line
@@ -87,14 +87,18 @@ public function testCopyCodebaseExclude() {
      ],
    ]);

    // Mock BuildTestBase so that it thinks our VFS is the Drupal root.
    // Mock BuildTestBase so that it thinks our VFS is the Composer and Drupal
    // roots.
    /** @var \PHPUnit\Framework\MockObject\MockBuilder|\Drupal\BuildTests\Framework\BuildTestBase $base */
    $base = $this->getMockBuilder(BuildTestBase::class)
      ->onlyMethods(['getDrupalRoot'])
      ->onlyMethods(['getDrupalRoot', 'getComposerRoot'])
      ->getMockForAbstractClass();
    $base->expects($this->exactly(2))
    $base->expects($this->exactly(1))
      ->method('getDrupalRoot')
      ->willReturn(vfsStream::url('drupal'));
    $base->expects($this->exactly(3))
      ->method('getComposerRoot')
      ->willReturn(vfsStream::url('drupal'));

    $base->setUp();

@@ -121,6 +125,84 @@ public function testCopyCodebaseExclude() {
    $base->tearDown();
  }

  /**
   * Tests copying codebase when Drupal and Composer roots are different.
   *
   * @covers ::copyCodebase
   */
  public function testCopyCodebaseDocRoot() {
    // Create a virtual file system containing items that should be
    // excluded. Exception being modules directory.
    vfsStream::setup('drupal', NULL, [
      'docroot' => [
        'sites' => [
          'default' => [
            'files' => [
              'a_file.txt' => 'some file.',
            ],
            'settings.php' => '<?php $settings = "stuff";',
            'settings.local.php' => '<?php $settings = "override";',
            'default.settings.php' => '<?php $settings = "default";',
          ],
          'simpletest' => [
            'simpletest_hash' => [
              'some_results.xml' => '<xml/>',
            ],
          ],
        ],
        'modules' => [
          'my_module' => [
            'vendor' => [
              'my_vendor' => [
                'composer.json' => "{\n}",
              ],
            ],
          ],
        ],
      ],
      'vendor' => [
        'test.txt' => 'File exists',
      ],
    ]);

    // Mock BuildTestBase so that it thinks our VFS is the Composer and Drupal
    // roots.
    /** @var \PHPUnit\Framework\MockObject\MockBuilder|\Drupal\BuildTests\Framework\BuildTestBase $base */
    $base = $this->getMockBuilder(BuildTestBase::class)
      ->onlyMethods(['getDrupalRoot', 'getComposerRoot'])
      ->getMockForAbstractClass();
    $base->expects($this->exactly(3))
      ->method('getDrupalRoot')
      ->willReturn(vfsStream::url('drupal/docroot'));
    $base->expects($this->exactly(5))
      ->method('getComposerRoot')
      ->willReturn(vfsStream::url('drupal'));

    $base->setUp();

    // Perform the copy.
    $base->copyCodebase();
    $full_path = $base->getWorkspaceDirectory();

    $this->assertDirectoryExists($full_path . '/docroot');

    // Verify expected files exist.
    $this->assertFileExists($full_path . DIRECTORY_SEPARATOR . 'docroot/modules/my_module/vendor/my_vendor/composer.json');
    $this->assertFileExists($full_path . DIRECTORY_SEPARATOR . 'docroot/sites/default/default.settings.php');
    $this->assertFileExists($full_path . DIRECTORY_SEPARATOR . 'vendor');

    // Verify expected files do not exist
    $this->assertFileDoesNotExist($full_path . DIRECTORY_SEPARATOR . 'docroot/sites/default/settings.php');
    $this->assertFileDoesNotExist($full_path . DIRECTORY_SEPARATOR . 'docroot/sites/default/settings.local.php');
    $this->assertFileDoesNotExist($full_path . DIRECTORY_SEPARATOR . 'docroot/sites/default/files');

    // Ensure that the workspace Drupal root is calculated correctly.
    $this->assertSame($full_path . '/docroot/', $base->getWorkspaceDrupalRoot());
    $this->assertSame('docroot/', $base->getWorkingPathDrupalRoot());

    $base->tearDown();
  }

  /**
   * @covers ::findAvailablePort
   */