bootstrap.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. <?php
  2. /**
  3. * @file
  4. * Autoloader for Drupal PHPUnit testing.
  5. *
  6. * @see phpunit.xml.dist
  7. */
  8. use Drupal\Component\Assertion\Handle;
  9. /**
  10. * Finds all valid extension directories recursively within a given directory.
  11. *
  12. * @param string $scan_directory
  13. * The directory that should be recursively scanned.
  14. * @return array
  15. * An associative array of extension directories found within the scanned
  16. * directory, keyed by extension name.
  17. */
  18. function drupal_phpunit_find_extension_directories($scan_directory) {
  19. $extensions = array();
  20. $dirs = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($scan_directory, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS));
  21. foreach ($dirs as $dir) {
  22. if (strpos($dir->getPathname(), '.info.yml') !== FALSE) {
  23. // Cut off ".info.yml" from the filename for use as the extension name. We
  24. // use getRealPath() so that we can scan extensions represented by
  25. // directory aliases.
  26. $extensions[substr($dir->getFilename(), 0, -9)] = $dir->getPathInfo()
  27. ->getRealPath();
  28. }
  29. }
  30. return $extensions;
  31. }
  32. /**
  33. * Returns directories under which contributed extensions may exist.
  34. *
  35. * @param string $root
  36. * (optional) Path to the root of the Drupal installation.
  37. *
  38. * @return array
  39. * An array of directories under which contributed extensions may exist.
  40. */
  41. function drupal_phpunit_contrib_extension_directory_roots($root = NULL) {
  42. if ($root === NULL) {
  43. $root = dirname(dirname(__DIR__));
  44. }
  45. $paths = array(
  46. $root . '/core/modules',
  47. $root . '/core/profiles',
  48. $root . '/modules',
  49. $root . '/profiles',
  50. );
  51. $sites_path = $root . '/sites';
  52. // Note this also checks sites/../modules and sites/../profiles.
  53. foreach (scandir($sites_path) as $site) {
  54. if ($site[0] === '.' || $site === 'simpletest') {
  55. continue;
  56. }
  57. $path = "$sites_path/$site";
  58. $paths[] = is_dir("$path/modules") ? realpath("$path/modules") : NULL;
  59. $paths[] = is_dir("$path/profiles") ? realpath("$path/profiles") : NULL;
  60. }
  61. return array_filter($paths);
  62. }
  63. /**
  64. * Registers the namespace for each extension directory with the autoloader.
  65. *
  66. * @param array $dirs
  67. * An associative array of extension directories, keyed by extension name.
  68. *
  69. * @return array
  70. * An associative array of extension directories, keyed by their namespace.
  71. */
  72. function drupal_phpunit_get_extension_namespaces($dirs) {
  73. $namespaces = array();
  74. foreach ($dirs as $extension => $dir) {
  75. if (is_dir($dir . '/src')) {
  76. // Register the PSR-4 directory for module-provided classes.
  77. $namespaces['Drupal\\' . $extension . '\\'][] = $dir . '/src';
  78. }
  79. if (is_dir($dir . '/tests/src')) {
  80. // Register the PSR-4 directory for PHPUnit test classes.
  81. $namespaces['Drupal\\Tests\\' . $extension . '\\'][] = $dir . '/tests/src';
  82. }
  83. }
  84. return $namespaces;
  85. }
  86. // We define the COMPOSER_INSTALL constant, so that PHPUnit knows where to
  87. // autoload from. This is needed for tests run in isolation mode, because
  88. // phpunit.xml.dist is located in a non-default directory relative to the
  89. // PHPUnit executable.
  90. if (!defined('PHPUNIT_COMPOSER_INSTALL')) {
  91. define('PHPUNIT_COMPOSER_INSTALL', __DIR__ . '/../../autoload.php');
  92. }
  93. /**
  94. * Populate class loader with additional namespaces for tests.
  95. *
  96. * We run this in a function to avoid setting the class loader to a global
  97. * that can change. This change can cause unpredictable false positives for
  98. * phpunit's global state change watcher. The class loader can be retrieved from
  99. * composer at any time by requiring autoload.php.
  100. */
  101. function drupal_phpunit_populate_class_loader() {
  102. /** @var \Composer\Autoload\ClassLoader $loader */
  103. $loader = require __DIR__ . '/../../autoload.php';
  104. // Start with classes in known locations.
  105. $loader->add('Drupal\\Tests', __DIR__);
  106. $loader->add('Drupal\\KernelTests', __DIR__);
  107. $loader->add('Drupal\\FunctionalTests', __DIR__);
  108. $loader->add('Drupal\\FunctionalJavascriptTests', __DIR__);
  109. if (!isset($GLOBALS['namespaces'])) {
  110. // Scan for arbitrary extension namespaces from core and contrib.
  111. $extension_roots = drupal_phpunit_contrib_extension_directory_roots();
  112. $dirs = array_map('drupal_phpunit_find_extension_directories', $extension_roots);
  113. $dirs = array_reduce($dirs, 'array_merge', array());
  114. $GLOBALS['namespaces'] = drupal_phpunit_get_extension_namespaces($dirs);
  115. }
  116. foreach ($GLOBALS['namespaces'] as $prefix => $paths) {
  117. $loader->addPsr4($prefix, $paths);
  118. }
  119. return $loader;
  120. };
  121. // Do class loader population.
  122. drupal_phpunit_populate_class_loader();
  123. // Set sane locale settings, to ensure consistent string, dates, times and
  124. // numbers handling.
  125. // @see \Drupal\Core\DrupalKernel::bootEnvironment()
  126. setlocale(LC_ALL, 'C');
  127. // Set the default timezone. While this doesn't cause any tests to fail, PHP
  128. // complains if 'date.timezone' is not set in php.ini. The Australia/Sydney
  129. // timezone is chosen so all tests are run using an edge case scenario (UTC+10
  130. // and DST). This choice is made to prevent timezone related regressions and
  131. // reduce the fragility of the testing system in general.
  132. date_default_timezone_set('Australia/Sydney');
  133. // Runtime assertions. PHPUnit follows the php.ini assert.active setting for
  134. // runtime assertions. By default this setting is on. Here we make a call to
  135. // make PHP 5 and 7 handle assertion failures the same way, but this call does
  136. // not turn runtime assertions on if they weren't on already.
  137. Handle::register();