KernelTest.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\HttpKernel\Tests;
  11. use PHPUnit\Framework\TestCase;
  12. use Symfony\Component\Config\Loader\LoaderInterface;
  13. use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
  14. use Symfony\Component\DependencyInjection\ContainerBuilder;
  15. use Symfony\Component\DependencyInjection\ContainerInterface;
  16. use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
  17. use Symfony\Component\Filesystem\Exception\IOException;
  18. use Symfony\Component\Filesystem\Filesystem;
  19. use Symfony\Component\HttpFoundation\Request;
  20. use Symfony\Component\HttpFoundation\Response;
  21. use Symfony\Component\HttpKernel\Bundle\Bundle;
  22. use Symfony\Component\HttpKernel\Bundle\BundleInterface;
  23. use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
  24. use Symfony\Component\HttpKernel\DependencyInjection\ResettableServicePass;
  25. use Symfony\Component\HttpKernel\DependencyInjection\ServicesResetter;
  26. use Symfony\Component\HttpKernel\HttpKernel;
  27. use Symfony\Component\HttpKernel\HttpKernelInterface;
  28. use Symfony\Component\HttpKernel\Kernel;
  29. use Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest;
  30. use Symfony\Component\HttpKernel\Tests\Fixtures\KernelWithoutBundles;
  31. use Symfony\Component\HttpKernel\Tests\Fixtures\ResettableService;
  32. class KernelTest extends TestCase
  33. {
  34. protected function tearDown(): void
  35. {
  36. try {
  37. (new Filesystem())->remove(__DIR__.'/Fixtures/var');
  38. } catch (IOException $e) {
  39. }
  40. }
  41. public function testConstructor()
  42. {
  43. $env = 'test_env';
  44. $debug = true;
  45. $kernel = new KernelForTest($env, $debug);
  46. $this->assertEquals($env, $kernel->getEnvironment());
  47. $this->assertEquals($debug, $kernel->isDebug());
  48. $this->assertFalse($kernel->isBooted());
  49. $this->assertLessThanOrEqual(microtime(true), $kernel->getStartTime());
  50. }
  51. public function testEmptyEnv()
  52. {
  53. $this->expectException(\InvalidArgumentException::class);
  54. $this->expectExceptionMessage(sprintf('Invalid environment provided to "%s": the environment cannot be empty.', KernelForTest::class));
  55. new KernelForTest('', false);
  56. }
  57. public function testClone()
  58. {
  59. $env = 'test_env';
  60. $debug = true;
  61. $kernel = new KernelForTest($env, $debug);
  62. $clone = clone $kernel;
  63. $this->assertEquals($env, $clone->getEnvironment());
  64. $this->assertEquals($debug, $clone->isDebug());
  65. $this->assertFalse($clone->isBooted());
  66. $this->assertLessThanOrEqual(microtime(true), $clone->getStartTime());
  67. }
  68. public function testClassNameValidityGetter()
  69. {
  70. $this->expectException(\InvalidArgumentException::class);
  71. $this->expectExceptionMessage('The environment "test.env" contains invalid characters, it can only contain characters allowed in PHP class names.');
  72. // We check the classname that will be generated by using a $env that
  73. // contains invalid characters.
  74. $env = 'test.env';
  75. $kernel = new KernelForTest($env, false, false);
  76. $kernel->boot();
  77. }
  78. public function testInitializeContainerClearsOldContainers()
  79. {
  80. $fs = new Filesystem();
  81. $legacyContainerDir = __DIR__.'/Fixtures/var/cache/custom/ContainerA123456';
  82. $fs->mkdir($legacyContainerDir);
  83. touch($legacyContainerDir.'.legacy');
  84. $kernel = new CustomProjectDirKernel();
  85. $kernel->boot();
  86. $containerDir = __DIR__.'/Fixtures/var/cache/custom/'.substr(\get_class($kernel->getContainer()), 0, 16);
  87. $this->assertTrue(unlink(__DIR__.'/Fixtures/var/cache/custom/Symfony_Component_HttpKernel_Tests_CustomProjectDirKernelCustomDebugContainer.php.meta'));
  88. $this->assertFileExists($containerDir);
  89. $this->assertFileDoesNotExist($containerDir.'.legacy');
  90. $kernel = new CustomProjectDirKernel(function ($container) { $container->register('foo', 'stdClass')->setPublic(true); });
  91. $kernel->boot();
  92. $this->assertFileExists($containerDir);
  93. $this->assertFileExists($containerDir.'.legacy');
  94. $this->assertFileDoesNotExist($legacyContainerDir);
  95. $this->assertFileDoesNotExist($legacyContainerDir.'.legacy');
  96. }
  97. public function testBootInitializesBundlesAndContainer()
  98. {
  99. $kernel = $this->getKernel(['initializeBundles']);
  100. $kernel->expects($this->once())
  101. ->method('initializeBundles');
  102. $kernel->boot();
  103. }
  104. public function testBootSetsTheContainerToTheBundles()
  105. {
  106. $bundle = $this->createMock(Bundle::class);
  107. $bundle->expects($this->once())
  108. ->method('setContainer');
  109. $kernel = $this->getKernel(['initializeBundles', 'getBundles']);
  110. $kernel->expects($this->once())
  111. ->method('getBundles')
  112. ->willReturn([$bundle]);
  113. $kernel->boot();
  114. }
  115. public function testBootSetsTheBootedFlagToTrue()
  116. {
  117. // use test kernel to access isBooted()
  118. $kernel = $this->getKernel(['initializeBundles']);
  119. $kernel->boot();
  120. $this->assertTrue($kernel->isBooted());
  121. }
  122. public function testClassCacheIsNotLoadedByDefault()
  123. {
  124. $kernel = $this->getKernel(['initializeBundles'], [], false, ['doLoadClassCache']);
  125. $kernel->expects($this->never())
  126. ->method('doLoadClassCache');
  127. $kernel->boot();
  128. }
  129. public function testBootKernelSeveralTimesOnlyInitializesBundlesOnce()
  130. {
  131. $kernel = $this->getKernel(['initializeBundles']);
  132. $kernel->expects($this->once())
  133. ->method('initializeBundles');
  134. $kernel->boot();
  135. $kernel->boot();
  136. }
  137. public function testShutdownCallsShutdownOnAllBundles()
  138. {
  139. $bundle = $this->createMock(Bundle::class);
  140. $bundle->expects($this->once())
  141. ->method('shutdown');
  142. $kernel = $this->getKernel([], [$bundle]);
  143. $kernel->boot();
  144. $kernel->shutdown();
  145. }
  146. public function testShutdownGivesNullContainerToAllBundles()
  147. {
  148. $bundle = $this->createMock(Bundle::class);
  149. $bundle->expects($this->exactly(2))
  150. ->method('setContainer')
  151. ->willReturnCallback(function ($container) {
  152. if (null !== $container) {
  153. $this->assertInstanceOf(ContainerInterface::class, $container);
  154. }
  155. })
  156. ;
  157. $kernel = $this->getKernel(['getBundles']);
  158. $kernel->expects($this->any())
  159. ->method('getBundles')
  160. ->willReturn([$bundle]);
  161. $kernel->boot();
  162. $kernel->shutdown();
  163. }
  164. public function testHandleCallsHandleOnHttpKernel()
  165. {
  166. $type = HttpKernelInterface::MAIN_REQUEST;
  167. $catch = true;
  168. $request = new Request();
  169. $httpKernelMock = $this->getMockBuilder(HttpKernel::class)
  170. ->disableOriginalConstructor()
  171. ->getMock();
  172. $httpKernelMock
  173. ->expects($this->once())
  174. ->method('handle')
  175. ->with($request, $type, $catch);
  176. $kernel = $this->getKernel(['getHttpKernel']);
  177. $kernel->expects($this->once())
  178. ->method('getHttpKernel')
  179. ->willReturn($httpKernelMock);
  180. $kernel->handle($request, $type, $catch);
  181. }
  182. public function testHandleBootsTheKernel()
  183. {
  184. $type = HttpKernelInterface::MAIN_REQUEST;
  185. $catch = true;
  186. $request = new Request();
  187. $httpKernelMock = $this->getMockBuilder(HttpKernel::class)
  188. ->disableOriginalConstructor()
  189. ->getMock();
  190. $kernel = $this->getKernel(['getHttpKernel', 'boot']);
  191. $kernel->expects($this->once())
  192. ->method('getHttpKernel')
  193. ->willReturn($httpKernelMock);
  194. $kernel->expects($this->once())
  195. ->method('boot');
  196. $kernel->handle($request, $type, $catch);
  197. }
  198. /**
  199. * @dataProvider getStripCommentsCodes
  200. */
  201. public function testStripComments(string $source, string $expected)
  202. {
  203. $output = Kernel::stripComments($source);
  204. // Heredocs are preserved, making the output mixing Unix and Windows line
  205. // endings, switching to "\n" everywhere on Windows to avoid failure.
  206. if ('\\' === \DIRECTORY_SEPARATOR) {
  207. $expected = str_replace("\r\n", "\n", $expected);
  208. $output = str_replace("\r\n", "\n", $output);
  209. }
  210. $this->assertEquals($expected, $output);
  211. }
  212. public static function getStripCommentsCodes(): array
  213. {
  214. return [
  215. ['<?php echo foo();', '<?php echo foo();'],
  216. ['<?php echo/**/foo();', '<?php echo foo();'],
  217. ['<?php echo/** bar */foo();', '<?php echo foo();'],
  218. ['<?php /**/echo foo();', '<?php echo foo();'],
  219. ['<?php echo \foo();', '<?php echo \foo();'],
  220. ['<?php echo/**/\foo();', '<?php echo \foo();'],
  221. ['<?php echo/** bar */\foo();', '<?php echo \foo();'],
  222. ['<?php /**/echo \foo();', '<?php echo \foo();'],
  223. [<<<'EOF'
  224. <?php
  225. include_once \dirname(__DIR__).'/foo.php';
  226. $string = 'string should not be modified';
  227. $string = 'string should not be
  228. modified';
  229. $heredoc = <<<HD
  230. Heredoc should not be modified {$a[1+$b]}
  231. HD;
  232. $nowdoc = <<<'ND'
  233. Nowdoc should not be modified
  234. ND;
  235. /**
  236. * some class comments to strip
  237. */
  238. class TestClass
  239. {
  240. /**
  241. * some method comments to strip
  242. */
  243. public function doStuff()
  244. {
  245. // inline comment
  246. }
  247. }
  248. EOF
  249. , <<<'EOF'
  250. <?php
  251. include_once \dirname(__DIR__).'/foo.php';
  252. $string = 'string should not be modified';
  253. $string = 'string should not be
  254. modified';
  255. $heredoc = <<<HD
  256. Heredoc should not be modified {$a[1+$b]}
  257. HD;
  258. $nowdoc = <<<'ND'
  259. Nowdoc should not be modified
  260. ND;
  261. class TestClass
  262. {
  263. public function doStuff()
  264. {
  265. }
  266. }
  267. EOF
  268. ],
  269. ];
  270. }
  271. public function testSerialize()
  272. {
  273. $env = 'test_env';
  274. $debug = true;
  275. $kernel = new KernelForTest($env, $debug);
  276. $expected = "O:57:\"Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest\":2:{s:14:\"\0*\0environment\";s:8:\"test_env\";s:8:\"\0*\0debug\";b:1;}";
  277. $this->assertEquals($expected, serialize($kernel));
  278. }
  279. public function testLocateResourceThrowsExceptionWhenNameIsNotValid()
  280. {
  281. $this->expectException(\InvalidArgumentException::class);
  282. $this->getKernel()->locateResource('Foo');
  283. }
  284. public function testLocateResourceThrowsExceptionWhenNameIsUnsafe()
  285. {
  286. $this->expectException(\RuntimeException::class);
  287. $this->getKernel()->locateResource('@FooBundle/../bar');
  288. }
  289. public function testLocateResourceThrowsExceptionWhenBundleDoesNotExist()
  290. {
  291. $this->expectException(\InvalidArgumentException::class);
  292. $this->getKernel()->locateResource('@FooBundle/config/routing.xml');
  293. }
  294. public function testLocateResourceThrowsExceptionWhenResourceDoesNotExist()
  295. {
  296. $this->expectException(\InvalidArgumentException::class);
  297. $kernel = $this->getKernel(['getBundle']);
  298. $kernel
  299. ->expects($this->once())
  300. ->method('getBundle')
  301. ->willReturn($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'))
  302. ;
  303. $kernel->locateResource('@Bundle1Bundle/config/routing.xml');
  304. }
  305. public function testLocateResourceReturnsTheFirstThatMatches()
  306. {
  307. $kernel = $this->getKernel(['getBundle']);
  308. $kernel
  309. ->expects($this->once())
  310. ->method('getBundle')
  311. ->willReturn($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'))
  312. ;
  313. $this->assertEquals(__DIR__.'/Fixtures/Bundle1Bundle/foo.txt', $kernel->locateResource('@Bundle1Bundle/foo.txt'));
  314. }
  315. public function testLocateResourceOnDirectories()
  316. {
  317. $kernel = $this->getKernel(['getBundle']);
  318. $kernel
  319. ->expects($this->exactly(2))
  320. ->method('getBundle')
  321. ->willReturn($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle', null, null, 'Bundle1Bundle'))
  322. ;
  323. $this->assertEquals(
  324. __DIR__.'/Fixtures/Bundle1Bundle/Resources/',
  325. $kernel->locateResource('@Bundle1Bundle/Resources/')
  326. );
  327. $this->assertEquals(
  328. __DIR__.'/Fixtures/Bundle1Bundle/Resources',
  329. $kernel->locateResource('@Bundle1Bundle/Resources')
  330. );
  331. }
  332. public function testInitializeBundleThrowsExceptionWhenRegisteringTwoBundlesWithTheSameName()
  333. {
  334. $this->expectException(\LogicException::class);
  335. $this->expectExceptionMessage('Trying to register two bundles with the same name "DuplicateName"');
  336. $fooBundle = $this->getBundle(__DIR__.'/Fixtures/FooBundle', null, 'FooBundle', 'DuplicateName');
  337. $barBundle = $this->getBundle(__DIR__.'/Fixtures/BarBundle', null, 'BarBundle', 'DuplicateName');
  338. $kernel = $this->getKernel([], [$fooBundle, $barBundle]);
  339. $kernel->boot();
  340. }
  341. public function testTerminateReturnsSilentlyIfKernelIsNotBooted()
  342. {
  343. $kernel = $this->getKernel(['getHttpKernel']);
  344. $kernel->expects($this->never())
  345. ->method('getHttpKernel');
  346. $kernel->terminate(Request::create('/'), new Response());
  347. }
  348. public function testTerminateDelegatesTerminationOnlyForTerminableInterface()
  349. {
  350. // does not implement TerminableInterface
  351. $httpKernel = new TestKernel();
  352. $kernel = $this->getKernel(['getHttpKernel']);
  353. $kernel->expects($this->once())
  354. ->method('getHttpKernel')
  355. ->willReturn($httpKernel);
  356. $kernel->boot();
  357. $kernel->terminate(Request::create('/'), new Response());
  358. $this->assertFalse($httpKernel->terminateCalled, 'terminate() is never called if the kernel class does not implement TerminableInterface');
  359. // implements TerminableInterface
  360. $httpKernelMock = $this->getMockBuilder(HttpKernel::class)
  361. ->disableOriginalConstructor()
  362. ->onlyMethods(['terminate'])
  363. ->getMock();
  364. $httpKernelMock
  365. ->expects($this->once())
  366. ->method('terminate');
  367. $kernel = $this->getKernel(['getHttpKernel']);
  368. $kernel->expects($this->exactly(2))
  369. ->method('getHttpKernel')
  370. ->willReturn($httpKernelMock);
  371. $kernel->boot();
  372. $kernel->terminate(Request::create('/'), new Response());
  373. }
  374. public function testKernelWithoutBundles()
  375. {
  376. $kernel = new KernelWithoutBundles('test', true);
  377. $kernel->boot();
  378. $this->assertTrue($kernel->getContainer()->getParameter('test_executed'));
  379. }
  380. public function testProjectDirExtension()
  381. {
  382. $kernel = new CustomProjectDirKernel();
  383. $kernel->boot();
  384. $this->assertSame(__DIR__.'/Fixtures', $kernel->getProjectDir());
  385. $this->assertSame(__DIR__.\DIRECTORY_SEPARATOR.'Fixtures', $kernel->getContainer()->getParameter('kernel.project_dir'));
  386. }
  387. public function testKernelReset()
  388. {
  389. $this->tearDown();
  390. $kernel = new CustomProjectDirKernel();
  391. $kernel->boot();
  392. $containerClass = \get_class($kernel->getContainer());
  393. $containerFile = (new \ReflectionClass($kernel->getContainer()))->getFileName();
  394. unlink(__DIR__.'/Fixtures/var/cache/custom/Symfony_Component_HttpKernel_Tests_CustomProjectDirKernelCustomDebugContainer.php.meta');
  395. $kernel = new CustomProjectDirKernel();
  396. $kernel->boot();
  397. $this->assertInstanceOf($containerClass, $kernel->getContainer());
  398. $this->assertFileExists($containerFile);
  399. unlink(__DIR__.'/Fixtures/var/cache/custom/Symfony_Component_HttpKernel_Tests_CustomProjectDirKernelCustomDebugContainer.php.meta');
  400. $kernel = new CustomProjectDirKernel(function ($container) { $container->register('foo', 'stdClass')->setPublic(true); });
  401. $kernel->boot();
  402. $this->assertNotInstanceOf($containerClass, $kernel->getContainer());
  403. $this->assertFileExists($containerFile);
  404. $this->assertFileExists(\dirname($containerFile).'.legacy');
  405. }
  406. public function testKernelExtension()
  407. {
  408. $kernel = new class() extends CustomProjectDirKernel implements ExtensionInterface {
  409. public function load(array $configs, ContainerBuilder $container)
  410. {
  411. $container->setParameter('test.extension-registered', true);
  412. }
  413. public function getNamespace(): string
  414. {
  415. return '';
  416. }
  417. /**
  418. * @return string|false
  419. */
  420. public function getXsdValidationBasePath()
  421. {
  422. return false;
  423. }
  424. public function getAlias(): string
  425. {
  426. return 'test-extension';
  427. }
  428. };
  429. $kernel->boot();
  430. $this->assertTrue($kernel->getContainer()->getParameter('test.extension-registered'));
  431. }
  432. public function testKernelPass()
  433. {
  434. $kernel = new PassKernel();
  435. $kernel->boot();
  436. $this->assertTrue($kernel->getContainer()->getParameter('test.processed'));
  437. }
  438. public function testWarmup()
  439. {
  440. $kernel = new CustomProjectDirKernel();
  441. $kernel->boot();
  442. $this->assertTrue($kernel->warmedUp);
  443. }
  444. public function testServicesResetter()
  445. {
  446. $httpKernelMock = $this->getMockBuilder(HttpKernelInterface::class)
  447. ->disableOriginalConstructor()
  448. ->getMock();
  449. $httpKernelMock
  450. ->expects($this->exactly(2))
  451. ->method('handle');
  452. $kernel = new CustomProjectDirKernel(function ($container) {
  453. $container->addCompilerPass(new ResettableServicePass());
  454. $container->register('one', ResettableService::class)
  455. ->setPublic(true)
  456. ->addTag('kernel.reset', ['method' => 'reset']);
  457. $container->register('services_resetter', ServicesResetter::class)->setPublic(true);
  458. }, $httpKernelMock, 'resetting');
  459. ResettableService::$counter = 0;
  460. $request = new Request();
  461. $kernel->handle($request);
  462. $kernel->getContainer()->get('one');
  463. $this->assertEquals(0, ResettableService::$counter);
  464. $this->assertFalse($kernel->getContainer()->initialized('services_resetter'));
  465. $kernel->handle($request);
  466. $this->assertEquals(1, ResettableService::$counter);
  467. }
  468. /**
  469. * @group time-sensitive
  470. */
  471. public function testKernelStartTimeIsResetWhileBootingAlreadyBootedKernel()
  472. {
  473. $kernel = $this->getKernel(['initializeBundles'], [], true);
  474. $kernel->boot();
  475. $preReBoot = $kernel->getStartTime();
  476. sleep(3600); // Intentionally large value to detect if ClockMock ever breaks
  477. $kernel->reboot(null);
  478. $this->assertGreaterThan($preReBoot, $kernel->getStartTime());
  479. }
  480. public function testAnonymousKernelGeneratesValidContainerClass()
  481. {
  482. $kernel = new class('test', true) extends Kernel {
  483. public function registerBundles(): iterable
  484. {
  485. return [];
  486. }
  487. public function registerContainerConfiguration(LoaderInterface $loader): void
  488. {
  489. }
  490. public function getContainerClass(): string
  491. {
  492. return parent::getContainerClass();
  493. }
  494. };
  495. $this->assertMatchesRegularExpression('/^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*TestDebugContainer$/', $kernel->getContainerClass());
  496. }
  497. /**
  498. * Returns a mock for the BundleInterface.
  499. */
  500. protected function getBundle($dir = null, $parent = null, $className = null, $bundleName = null): BundleInterface
  501. {
  502. $bundle = $this
  503. ->getMockBuilder(BundleInterface::class)
  504. ->onlyMethods(['getPath', 'getName'])
  505. ->disableOriginalConstructor()
  506. ;
  507. if ($className) {
  508. $bundle->setMockClassName($className);
  509. }
  510. $bundle = $bundle->getMockForAbstractClass();
  511. $bundle
  512. ->expects($this->any())
  513. ->method('getName')
  514. ->willReturn($bundleName ?? \get_class($bundle))
  515. ;
  516. $bundle
  517. ->expects($this->any())
  518. ->method('getPath')
  519. ->willReturn($dir)
  520. ;
  521. return $bundle;
  522. }
  523. /**
  524. * Returns a mock for the abstract kernel.
  525. *
  526. * @param array $methods Additional methods to mock (besides the abstract ones)
  527. * @param array $bundles Bundles to register
  528. */
  529. protected function getKernel(array $methods = [], array $bundles = [], bool $debug = false, array $methodsToAdd = []): Kernel
  530. {
  531. $methods[] = 'registerBundles';
  532. $kernelMockBuilder = $this
  533. ->getMockBuilder(KernelForTest::class)
  534. ->onlyMethods($methods)
  535. ->setConstructorArgs(['test', $debug])
  536. ;
  537. if (0 !== \count($methodsToAdd)) {
  538. $kernelMockBuilder->addMethods($methodsToAdd);
  539. }
  540. $kernel = $kernelMockBuilder->getMock();
  541. $kernel->expects($this->any())
  542. ->method('registerBundles')
  543. ->willReturn($bundles)
  544. ;
  545. return $kernel;
  546. }
  547. }
  548. class TestKernel implements HttpKernelInterface
  549. {
  550. public $terminateCalled = false;
  551. public function terminate()
  552. {
  553. $this->terminateCalled = true;
  554. }
  555. public function handle(Request $request, int $type = self::MAIN_REQUEST, bool $catch = true): Response
  556. {
  557. }
  558. public function getProjectDir(): string
  559. {
  560. return __DIR__.'/Fixtures';
  561. }
  562. }
  563. class CustomProjectDirKernel extends Kernel implements WarmableInterface
  564. {
  565. public $warmedUp = false;
  566. private $baseDir;
  567. private $buildContainer;
  568. private $httpKernel;
  569. public function __construct(\Closure $buildContainer = null, HttpKernelInterface $httpKernel = null, $env = 'custom')
  570. {
  571. parent::__construct($env, true);
  572. $this->buildContainer = $buildContainer;
  573. $this->httpKernel = $httpKernel;
  574. }
  575. public function registerBundles(): iterable
  576. {
  577. return [];
  578. }
  579. public function registerContainerConfiguration(LoaderInterface $loader)
  580. {
  581. }
  582. public function getProjectDir(): string
  583. {
  584. return __DIR__.'/Fixtures';
  585. }
  586. public function warmUp(string $cacheDir): array
  587. {
  588. $this->warmedUp = true;
  589. return [];
  590. }
  591. protected function build(ContainerBuilder $container)
  592. {
  593. if ($build = $this->buildContainer) {
  594. $build($container);
  595. }
  596. }
  597. protected function getHttpKernel(): HttpKernelInterface
  598. {
  599. return $this->httpKernel;
  600. }
  601. }
  602. class PassKernel extends CustomProjectDirKernel implements CompilerPassInterface
  603. {
  604. public function __construct()
  605. {
  606. parent::__construct();
  607. Kernel::__construct('pass', true);
  608. }
  609. public function process(ContainerBuilder $container)
  610. {
  611. $container->setParameter('test.processed', true);
  612. }
  613. }