public function testProcessesIncludesAndCacheTheResultOfEachIncludedFile() { $mainFile = '/path/to/main.yml'; $parsedMainFileContent = ['include' => ['file1.yml', 'another_level/file2.yml'], 'Nelmio\\Alice\\Model\\User' => ['user_main' => []]]; $parsedFile1Content = ['Nelmio\\Alice\\Model\\User' => ['user_file1' => []]]; $parsedFile2Content = ['include' => ['/path/to/file3.yml'], 'Nelmio\\Alice\\Model\\User' => ['user_file2' => []]]; $parsedFile3Content = ['Nelmio\\Alice\\Model\\User' => ['user_file3' => []]]; $expected = ['Nelmio\\Alice\\Model\\User' => ['user_file3' => [], 'user_file2' => [], 'user_file1' => [], 'user_main' => []]]; $expectedFile2 = ['Nelmio\\Alice\\Model\\User' => ['user_file3' => [], 'user_file2' => []]]; $fileLocatorProphecy = $this->prophesize(FileLocatorInterface::class); $fileLocatorProphecy->locate($mainFile)->willReturn($mainFile); $fileLocatorProphecy->locate('file1.yml', '/path/to')->willReturn('/path/to/file1.yml'); $fileLocatorProphecy->locate('/path/to/file1.yml')->willReturn('/path/to/file1.yml'); $fileLocatorProphecy->locate('another_level/file2.yml', '/path/to')->willReturn('/path/to/file2.yml'); $fileLocatorProphecy->locate('/path/to/file2.yml')->willReturn('/path/to/file2.yml'); $fileLocatorProphecy->locate('/path/to/file3.yml', '/path/to')->willReturn('/path/to/file3.yml'); $fileLocatorProphecy->locate('/path/to/file3.yml')->willReturn('/path/to/file3.yml'); /** @var FileLocatorInterface $fileLocator */ $fileLocator = $fileLocatorProphecy->reveal(); $decoratedParserProphecy = $this->prophesize(ParserInterface::class); $decoratedParserProphecy->parse('/path/to/main.yml')->willReturn($parsedMainFileContent); $decoratedParserProphecy->parse('/path/to/file1.yml')->willReturn($parsedFile1Content); $decoratedParserProphecy->parse('/path/to/file2.yml')->willReturn($parsedFile2Content); $decoratedParserProphecy->parse('/path/to/file3.yml')->willReturn($parsedFile3Content); /* @var ParserInterface $decoratedParser */ $decoratedParser = $decoratedParserProphecy->reveal(); $parser = new RuntimeCacheParser($decoratedParser, $fileLocator, new DefaultIncludeProcessor($fileLocator)); $actual = $parser->parse($mainFile); $this->assertSame($expected, $actual); $decoratedParserProphecy->parse(Argument::any())->shouldHaveBeenCalledTimes(4); $fileLocatorProphecy->locate(Argument::any())->shouldHaveBeenCalledTimes(4); // As the parser cache the results, parsing each file does not re-trigger a parse call $fileLocatorProphecy->locate('file1.yml')->willReturn('/path/to/file1.yml'); $fileLocatorProphecy->locate('file2.yml')->willReturn('/path/to/file2.yml'); $fileLocatorProphecy->locate('file3.yml')->willReturn('/path/to/file3.yml'); $actual = $parser->parse($mainFile); $actualFile1 = $parser->parse('file1.yml'); $actualFile2 = $parser->parse('file2.yml'); $actualFile3 = $parser->parse('file3.yml'); $this->assertSame($expected, $actual); $this->assertSame($parsedFile1Content, $actualFile1); $this->assertSame($expectedFile2, $actualFile2); $this->assertSame($parsedFile3Content, $actualFile3); $decoratedParserProphecy->parse(Argument::any())->shouldHaveBeenCalledTimes(4); $fileLocatorProphecy->locate(Argument::any())->shouldHaveBeenCalledTimes(4 + 4); }