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);
}