fileProvider = $this->prophesize(FileProvider::class); } /** * @return void */ public function testLoadShouldParseXmlBaselineToPhpArray() { $baselineFilePath = 'baseline.xml'; $this->fileProvider->fileExists($baselineFilePath)->willReturn(true); $this->fileProvider->getContents($baselineFilePath)->willReturn( ' foo bar foo bar ' ); $expectedParsedBaseline = [ 'sample/sample-file.php' => [ 'MixedAssignment' => ['o' => 2, 's' => ['foo', 'bar']], 'InvalidReturnStatement' => ['o' => 1, 's' => []], ], 'sample/sample-file2.php' => [ 'PossiblyUnusedMethod' => ['o' => 2, 's' => ['foo', 'bar']], ], ]; $this->assertSame( $expectedParsedBaseline, ErrorBaseline::read($this->fileProvider->reveal(), $baselineFilePath) ); } public function testLoadShouldIgnoreLineEndingsInIssueSnippet(): void { $baselineFilePath = 'baseline.xml'; $this->fileProvider->fileExists($baselineFilePath)->willReturn(true); $this->fileProvider->getContents($baselineFilePath)->willReturn( " foo\r " ); $expectedParsedBaseline = [ 'sample/sample-file.php' => [ 'MixedAssignment' => ['o' => 1, 's' => ['foo']], ], ]; $this->assertSame( $expectedParsedBaseline, ErrorBaseline::read($this->fileProvider->reveal(), $baselineFilePath) ); } /** * @return void */ public function testLoadShouldThrowExceptionWhenFilesAreNotDefinedInBaselineFile() { $this->expectException(ConfigException::class); $baselineFile = 'baseline.xml'; $this->fileProvider->fileExists($baselineFile)->willReturn(true); $this->fileProvider->getContents($baselineFile)->willReturn( ' ' ); ErrorBaseline::read($this->fileProvider->reveal(), $baselineFile); } /** * @return void */ public function testLoadShouldThrowExceptionWhenBaselineFileDoesNotExist() { $this->expectException(ConfigException::class); $baselineFile = 'baseline.xml'; $this->fileProvider->fileExists($baselineFile)->willReturn(false); ErrorBaseline::read($this->fileProvider->reveal(), $baselineFile); } /** * @return void */ public function testCountTotalIssuesShouldReturnCorrectNumber() { $existingIssues = [ 'sample/sample-file.php' => [ 'MixedAssignment' => ['o' => 2, 's' => ['bar']], 'MixedOperand' => ['o' => 2, 's' => []], ], 'sample/sample-file2.php' => [ 'TypeCoercion' => ['o' => 1, 's' => []], ], ]; $totalIssues = ErrorBaseline::countTotalIssues($existingIssues); $this->assertSame($totalIssues, 5); } /** * @return void */ public function testCreateShouldAggregateIssuesPerFile() { $baselineFile = 'baseline.xml'; $documentContent = null; $this->fileProvider->setContents( $baselineFile, Argument::that(function (string $document) use (&$documentContent): bool { $documentContent = $document; return true; }) ); ErrorBaseline::create( $this->fileProvider->reveal(), $baselineFile, [ 'sample/sample-file.php' => [ new \Psalm\Internal\Analyzer\IssueData( 'error', 0, 0, 'MixedAssignment', 'Message', 'sample/sample-file.php', 'sample/sample-file.php', 'foo', 'foo', 0, 0, 0, 0, 0, 0 ), new \Psalm\Internal\Analyzer\IssueData( 'error', 0, 0, 'MixedAssignment', 'Message', 'sample/sample-file.php', 'sample/sample-file.php', 'bar', 'bar', 0, 0, 0, 0, 0, 0 ), new \Psalm\Internal\Analyzer\IssueData( 'error', 0, 0, 'MixedAssignment', 'Message', 'sample/sample-file.php', 'sample/sample-file.php', 'bat', 'bat', 0, 0, 0, 0, 0, 0 ), new \Psalm\Internal\Analyzer\IssueData( 'error', 0, 0, 'MixedOperand', 'Message', 'sample/sample-file.php', 'sample/sample-file.php', 'bing', 'bing', 0, 0, 0, 0, 0, 0 ), new \Psalm\Internal\Analyzer\IssueData( 'info', 0, 0, 'AssignmentToVoid', 'Message', 'sample/sample-file.php', 'sample/sample-file.php', 'bong', 'bong', 0, 0, 0, 0, 0, 0 ), ], 'sample/sample-file2.php' => [ new \Psalm\Internal\Analyzer\IssueData( 'error', 0, 0, 'MixedAssignment', 'Message', 'sample/sample-file2.php', 'sample/sample-file2.php', 'boardy', 'boardy', 0, 0, 0, 0, 0, 0 ), new \Psalm\Internal\Analyzer\IssueData( 'error', 0, 0, 'MixedAssignment', 'Message', 'sample/sample-file2.php', 'sample/sample-file2.php', 'bardy', 'bardy', 0, 0, 0, 0, 0, 0 ), new \Psalm\Internal\Analyzer\IssueData( 'error', 0, 0, 'TypeCoercion', 'Message', 'sample/sample-file2.php', 'sample/sample-file2.php', 'hardy' . "\n", 'hardy' . "\n", 0, 0, 0, 0, 0, 0 ), ], ], false ); $baselineDocument = new \DOMDocument(); $baselineDocument->loadXML($documentContent, LIBXML_NOBLANKS); /** @var \DOMElement[] $files */ $files = $baselineDocument->getElementsByTagName('files')[0]->childNodes; [$file1, $file2] = $files; $this->assertSame('sample/sample-file.php', $file1->getAttribute('src')); $this->assertSame('sample/sample-file2.php', $file2->getAttribute('src')); /** @var \DOMElement[] $file1Issues */ $file1Issues = $file1->childNodes; /** @var \DOMElement[] $file2Issues */ $file2Issues = $file2->childNodes; $this->assertSame('MixedAssignment', $file1Issues[0]->tagName); $this->assertSame('3', $file1Issues[0]->getAttribute('occurrences')); $this->assertSame('MixedOperand', $file1Issues[1]->tagName); $this->assertSame('1', $file1Issues[1]->getAttribute('occurrences')); $this->assertSame('MixedAssignment', $file2Issues[0]->tagName); $this->assertSame('2', $file2Issues[0]->getAttribute('occurrences')); $this->assertSame('TypeCoercion', $file2Issues[1]->tagName); $this->assertSame('1', $file2Issues[1]->getAttribute('occurrences')); } /** * @return void */ public function testUpdateShouldRemoveExistingIssuesWithoutAddingNewOnes() { $baselineFile = 'baseline.xml'; $this->fileProvider->fileExists($baselineFile)->willReturn(true); $this->fileProvider->getContents($baselineFile)->willReturn( ' bar bat ' ); $this->fileProvider->setContents(Argument::cetera()); $newIssues = [ 'sample/sample-file.php' => [ new \Psalm\Internal\Analyzer\IssueData( 'error', 0, 0, 'MixedAssignment', 'Message', 'sample/sample-file.php', 'sample/sample-file.php', 'foo', 'foo', 0, 0, 0, 0, 0, 0 ), new \Psalm\Internal\Analyzer\IssueData( 'error', 0, 0, 'MixedAssignment', 'Message', 'sample/sample-file.php', 'sample/sample-file.php', 'bar', 'bar', 0, 0, 0, 0, 0, 0 ), new \Psalm\Internal\Analyzer\IssueData( 'error', 0, 0, 'MixedOperand', 'Message', 'sample/sample-file.php', 'sample/sample-file.php', 'bat', 'bat', 0, 0, 0, 0, 0, 0 ), new \Psalm\Internal\Analyzer\IssueData( 'error', 0, 0, 'MixedOperand', 'Message', 'sample/sample-file.php', 'sample/sample-file.php', 'bam', 'bam', 0, 0, 0, 0, 0, 0 ), ], 'sample/sample-file2.php' => [ new \Psalm\Internal\Analyzer\IssueData( 'error', 0, 0, 'TypeCoercion', 'Message', 'sample/sample-file2.php', 'sample/sample-file2.php', 'tar', 'tar', 0, 0, 0, 0, 0, 0 ), ], ]; $remainingBaseline = ErrorBaseline::update( $this->fileProvider->reveal(), $baselineFile, $newIssues, false ); $this->assertSame([ 'sample/sample-file.php' => [ 'MixedAssignment' => ['o' => 2, 's' => ['bar']], 'MixedOperand' => ['o' => 1, 's' => []], ], 'sample/sample-file2.php' => [ 'TypeCoercion' => ['o' => 1, 's' => []], ], ], $remainingBaseline); } /** * @return void */ public function testAddingACommentInBaselineDoesntTriggerNotice() { $baselineFilePath = 'baseline.xml'; $this->fileProvider->fileExists($baselineFilePath)->willReturn(true); $this->fileProvider->getContents($baselineFilePath)->willReturn( ' foo bar foo bar ' ); $expectedParsedBaseline = [ 'sample/sample-file.php' => [ 'MixedAssignment' => ['o' => 2, 's' => ['foo', 'bar']], 'InvalidReturnStatement' => ['o' => 1, 's' => []], ], 'sample/sample-file2.php' => [ 'PossiblyUnusedMethod' => ['o' => 2, 's' => ['foo', 'bar']], ], ]; $this->assertSame( $expectedParsedBaseline, ErrorBaseline::read($this->fileProvider->reveal(), $baselineFilePath) ); } }