DrupalKernelTest.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. <?php
  2. namespace Drupal\Tests\Core\DrupalKernel {
  3. use Drupal\Core\DrupalKernel;
  4. use Drupal\Tests\UnitTestCase;
  5. use org\bovigo\vfs\vfsStream;
  6. use Symfony\Component\ClassLoader\ApcClassLoader;
  7. use Symfony\Component\HttpFoundation\Request;
  8. /**
  9. * @coversDefaultClass \Drupal\Core\DrupalKernel
  10. * @group DrupalKernel
  11. */
  12. class DrupalKernelTest extends UnitTestCase {
  13. /**
  14. * Tests hostname validation with settings.
  15. *
  16. * @covers ::setupTrustedHosts
  17. * @dataProvider providerTestTrustedHosts
  18. */
  19. public function testTrustedHosts($host, $server_name, $message, $expected = FALSE) {
  20. $request = new Request();
  21. $trusted_host_patterns = [
  22. '^example\.com$',
  23. '^.+\.example\.com$',
  24. '^example\.org',
  25. '^.+\.example\.org',
  26. ];
  27. if (!empty($host)) {
  28. $request->headers->set('HOST', $host);
  29. }
  30. $request->server->set('SERVER_NAME', $server_name);
  31. $method = new \ReflectionMethod('Drupal\Core\DrupalKernel', 'setupTrustedHosts');
  32. $method->setAccessible(TRUE);
  33. $valid_host = $method->invoke(NULL, $request, $trusted_host_patterns);
  34. $this->assertSame($expected, $valid_host, $message);
  35. // Reset the trusted hosts because it is statically stored on the request.
  36. $method->invoke(NULL, $request, []);
  37. // Reset the request factory because it is statically stored on the request.
  38. Request::setFactory(NULL);
  39. }
  40. /**
  41. * Tests the reregistration of autoloaders if APCu available.
  42. *
  43. * This test runs in a separate process since it registers class loaders and
  44. * results in statics being set.
  45. *
  46. * @runInSeparateProcess
  47. * @preserveGlobalState disabled
  48. * @requires function apcu_fetch
  49. * @covers ::initializeSettings
  50. */
  51. public function testInitializeSettings() {
  52. $request = new Request();
  53. $classloader = new fakeAutoloader();
  54. // Create a kernel suitable for testing.
  55. $kernel = $this->getMockBuilder(DrupalKernel::class)
  56. ->disableOriginalConstructor()
  57. ->setMethods(['do_not_mock_any_methods'])
  58. ->getMock();
  59. $classloader_property = new \ReflectionProperty($kernel, 'classLoader');
  60. $classloader_property->setAccessible(TRUE);
  61. $classloader_property->setValue($kernel, $classloader);
  62. $method = new \ReflectionMethod($kernel, 'initializeSettings');
  63. $method->setAccessible(TRUE);
  64. // Prepend another autoloader to simulate Drush's autoloader.
  65. $fake_drush_autoloader = function () {
  66. return NULL;
  67. };
  68. spl_autoload_register($fake_drush_autoloader, TRUE, TRUE);
  69. // Before calling DrupalKernel::initializeSettings() the first autoloader
  70. // is the fake Drush autoloader.
  71. $this->assertSame($fake_drush_autoloader, spl_autoload_functions()[0]);
  72. // Call DrupalKernel::initializeSettings() to simulate part of a Drupal
  73. // bootstrap. During the include of autoload.php Composer would prepend
  74. // Drupal's autoloader and then this method should not result in Drush's
  75. // autoloader becoming the first autoloader even if it swaps out
  76. // Composer's autoloader for an optimised one.
  77. $method->invoke($kernel, $request);
  78. $autoloaders = spl_autoload_functions();
  79. // The first autoloader should be the APCu based autoloader.
  80. $this->assertInstanceOf(ApcClassLoader::class, $autoloaders[0][0]);
  81. // The second autoloader should be the original autoloader the kernel was
  82. // constructed with.
  83. $this->assertSame($classloader, $autoloaders[1][0]);
  84. // The third autoloader should be Drush's autoloader.
  85. $this->assertSame($fake_drush_autoloader, $autoloaders[2]);
  86. // Reset the request factory because it is statically stored on the
  87. // request.
  88. Request::setFactory(NULL);
  89. }
  90. /**
  91. * Provides test data for testTrustedHosts().
  92. */
  93. public function providerTestTrustedHosts() {
  94. $data = [];
  95. // Tests canonical URL.
  96. $data[] = [
  97. 'www.example.com',
  98. 'www.example.com',
  99. 'canonical URL is trusted',
  100. TRUE,
  101. ];
  102. // Tests missing hostname for HTTP/1.0 compatibility where the Host
  103. // header is optional.
  104. $data[] = [NULL, 'www.example.com', 'empty Host is valid', TRUE];
  105. // Tests the additional patterns from the settings.
  106. $data[] = [
  107. 'example.com',
  108. 'www.example.com',
  109. 'host from settings is trusted',
  110. TRUE,
  111. ];
  112. $data[] = [
  113. 'subdomain.example.com',
  114. 'www.example.com',
  115. 'host from settings is trusted',
  116. TRUE,
  117. ];
  118. $data[] = [
  119. 'www.example.org',
  120. 'www.example.com',
  121. 'host from settings is trusted',
  122. TRUE,
  123. ];
  124. $data[] = [
  125. 'example.org',
  126. 'www.example.com',
  127. 'host from settings is trusted',
  128. TRUE,
  129. ];
  130. // Tests mismatch.
  131. $data[] = [
  132. 'www.blackhat.com',
  133. 'www.example.com',
  134. 'unspecified host is untrusted',
  135. FALSE,
  136. ];
  137. return $data;
  138. }
  139. /**
  140. * Tests site path finding.
  141. *
  142. * This test is run in a separate process since it defines DRUPAL_ROOT. This
  143. * stops any possible pollution of other tests.
  144. *
  145. * @covers ::findSitePath
  146. * @runInSeparateProcess
  147. */
  148. public function testFindSitePath() {
  149. $vfs_root = vfsStream::setup('drupal_root');
  150. $sites_php = <<<'EOD'
  151. <?php
  152. $sites['8888.www.example.org'] = 'example';
  153. EOD;
  154. // Create the expected directory structure.
  155. vfsStream::create([
  156. 'sites' => [
  157. 'sites.php' => $sites_php,
  158. 'example' => [
  159. 'settings.php' => 'test',
  160. ],
  161. ],
  162. ]);
  163. $request = new Request();
  164. $request->server->set('SERVER_NAME', 'www.example.org');
  165. $request->server->set('SERVER_PORT', '8888');
  166. $request->server->set('SCRIPT_NAME', '/index.php');
  167. $this->assertEquals('sites/example', DrupalKernel::findSitePath($request, TRUE, $vfs_root->url('drupal_root')));
  168. $this->assertEquals('sites/example', DrupalKernel::findSitePath($request, FALSE, $vfs_root->url('drupal_root')));
  169. }
  170. }
  171. /**
  172. * A fake autoloader for testing
  173. */
  174. class FakeAutoloader {
  175. /**
  176. * Registers this instance as an autoloader.
  177. *
  178. * @param bool $prepend
  179. * Whether to prepend the autoloader or not
  180. */
  181. public function register($prepend = FALSE) {
  182. spl_autoload_register([$this, 'loadClass'], TRUE, $prepend);
  183. }
  184. /**
  185. * Unregisters this instance as an autoloader.
  186. */
  187. public function unregister() {
  188. spl_autoload_unregister([$this, 'loadClass']);
  189. }
  190. /**
  191. * Loads the given class or interface.
  192. *
  193. * @return null
  194. * This class never loads.
  195. */
  196. public function loadClass() {
  197. return NULL;
  198. }
  199. /**
  200. * Finds a file by class name while caching lookups to APC.
  201. *
  202. * @return null
  203. * This class never finds.
  204. */
  205. public function findFile() {
  206. return NULL;
  207. }
  208. }
  209. }
  210. namespace {
  211. if (!function_exists('drupal_valid_test_ua')) {
  212. function drupal_valid_test_ua($new_prefix = NULL) {
  213. return FALSE;
  214. }
  215. }
  216. }