From f172ebf0b55c51d0715a813b9228e4a6b865c5df Mon Sep 17 00:00:00 2001
From: Olivier Adam <olivier@getunlatch.com>
Date: Fri, 24 Nov 2023 18:03:27 +0100
Subject: [PATCH] add filename and line number to phpunit output

Remove xsd all together, as is the case in phpunit :

no xsd here :
https://github.com/sebastianbergmann/phpunit/blob/main/src/Logging/JUnit/JunitXmlLogger.php#L298

discussion of the absence of proper junit xsd here :
https://github.com/sebastianbergmann/phpunit/issues/2964
---
 .../ErrorFormatter/JunitErrorFormatter.php    |  15 ++-
 .../JunitErrorFormatterTest.php               |  35 +++---
 .../Command/ErrorFormatter/junit-schema.xsd   | 118 ------------------
 3 files changed, 27 insertions(+), 141 deletions(-)
 delete mode 100644 tests/PHPStan/Command/ErrorFormatter/junit-schema.xsd

diff --git a/src/Command/ErrorFormatter/JunitErrorFormatter.php b/src/Command/ErrorFormatter/JunitErrorFormatter.php
index 6e684ad942..599a299623 100644
--- a/src/Command/ErrorFormatter/JunitErrorFormatter.php
+++ b/src/Command/ErrorFormatter/JunitErrorFormatter.php
@@ -27,7 +27,7 @@ public function formatErrors(
 
 		$result = '<?xml version="1.0" encoding="UTF-8"?>';
 		$result .= sprintf(
-			'<testsuite failures="%d" name="phpstan" tests="%d" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/junit-team/junit5/r5.5.1/platform-tests/src/test/resources/jenkins-junit.xsd">',
+			'<testsuite failures="%d" name="phpstan" tests="%d">',
 			$totalFailuresCount,
 			$totalTestsCount,
 		);
@@ -38,6 +38,8 @@ public function formatErrors(
 				sprintf('%s:%s', $fileName, (string) $fileSpecificError->getLine()),
 				'ERROR',
 				$this->escape($fileSpecificError->getMessage()),
+				$fileName,
+				$fileSpecificError->getLine(),
 			);
 		}
 
@@ -65,9 +67,16 @@ public function formatErrors(
 	 *
 	 *
 	 */
-	private function createTestCase(string $reference, string $type, ?string $message = null): string
+	private function createTestCase(string $reference, string $type, ?string $message = null, ?string $fileName = null, ?int $lineNumber = null): string
 	{
-		$result = sprintf('<testcase name="%s">', $this->escape($reference));
+		$result = sprintf('<testcase name="%s"', $this->escape($reference));
+		if ($fileName !== null) {
+			$result .= sprintf(' file="%s"', $this->escape($fileName));
+		}
+		if ($lineNumber !== null) {
+			$result .= sprintf(' line="%s"', (string) $lineNumber);
+		}
+		$result .= '>';
 
 		if ($message !== null) {
 			$result .= sprintf('<failure type="%s" message="%s" />', $this->escape($type), $this->escape($message));
diff --git a/tests/PHPStan/Command/ErrorFormatter/JunitErrorFormatterTest.php b/tests/PHPStan/Command/ErrorFormatter/JunitErrorFormatterTest.php
index 7a913521ef..fd7a8fbc23 100644
--- a/tests/PHPStan/Command/ErrorFormatter/JunitErrorFormatterTest.php
+++ b/tests/PHPStan/Command/ErrorFormatter/JunitErrorFormatterTest.php
@@ -29,7 +29,7 @@ public function dataFormatterOutputProvider(): Generator
 			0,
 			0,
 			'<?xml version="1.0" encoding="UTF-8"?>
-<testsuite failures="0" name="phpstan" tests="1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/junit-team/junit5/r5.5.1/platform-tests/src/test/resources/jenkins-junit.xsd">
+<testsuite failures="0" name="phpstan" tests="1">
   <testcase name="phpstan"/>
 </testsuite>
 ',
@@ -40,8 +40,8 @@ public function dataFormatterOutputProvider(): Generator
 			1,
 			0,
 			'<?xml version="1.0" encoding="UTF-8"?>
-<testsuite failures="1" name="phpstan" tests="1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/junit-team/junit5/r5.5.1/platform-tests/src/test/resources/jenkins-junit.xsd">
-  <testcase name="folder with unicode &#x1F603;/file name with &quot;spaces&quot; and unicode &#x1F603;.php:4">
+<testsuite failures="1" name="phpstan" tests="1">
+  <testcase name="folder with unicode &#x1F603;/file name with &quot;spaces&quot; and unicode &#x1F603;.php:4" file="folder with unicode &#x1F603;/file name with &quot;spaces&quot; and unicode &#x1F603;.php" line="4">
     <failure type="ERROR" message="Foo" />
   </testcase>
 </testsuite>
@@ -53,7 +53,7 @@ public function dataFormatterOutputProvider(): Generator
 			0,
 			1,
 			'<?xml version="1.0" encoding="UTF-8"?>
-<testsuite failures="1" name="phpstan" tests="1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/junit-team/junit5/r5.5.1/platform-tests/src/test/resources/jenkins-junit.xsd">
+<testsuite failures="1" name="phpstan" tests="1">
   <testcase name="General error">
     <failure type="ERROR" message="first generic error" />
   </testcase>
@@ -66,17 +66,17 @@ public function dataFormatterOutputProvider(): Generator
 			4,
 			0,
 			'<?xml version="1.0" encoding="UTF-8"?>
-<testsuite failures="4" name="phpstan" tests="4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/junit-team/junit5/r5.5.1/platform-tests/src/test/resources/jenkins-junit.xsd">
-  <testcase name="folder with unicode &#x1F603;/file name with &quot;spaces&quot; and unicode &#x1F603;.php:2">
+<testsuite failures="4" name="phpstan" tests="4">
+  <testcase name="folder with unicode &#x1F603;/file name with &quot;spaces&quot; and unicode &#x1F603;.php:2" file="folder with unicode &#x1F603;/file name with &quot;spaces&quot; and unicode &#x1F603;.php" line="2">
     <failure type="ERROR" message="Bar Bar2" />
   </testcase>
-  <testcase name="folder with unicode &#x1F603;/file name with &quot;spaces&quot; and unicode &#x1F603;.php:4">
+  <testcase name="folder with unicode &#x1F603;/file name with &quot;spaces&quot; and unicode &#x1F603;.php:4" file="folder with unicode &#x1F603;/file name with &quot;spaces&quot; and unicode &#x1F603;.php" line="4">
     <failure type="ERROR" message="Foo" />
   </testcase>
-  <testcase name="foo.php:1">
+  <testcase name="foo.php:1" file="foo.php" line="1">
     <failure type="ERROR" message="Foo"/>
   </testcase>
-  <testcase name="foo.php:5">
+  <testcase name="foo.php:5" file="foo.php" line="5">
     <failure type="ERROR" message="Bar Bar2"/>
   </testcase>
 </testsuite>
@@ -88,7 +88,7 @@ public function dataFormatterOutputProvider(): Generator
 			0,
 			2,
 			'<?xml version="1.0" encoding="UTF-8"?>
-<testsuite failures="2" name="phpstan" tests="2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/junit-team/junit5/r5.5.1/platform-tests/src/test/resources/jenkins-junit.xsd">
+<testsuite failures="2" name="phpstan" tests="2">
   <testcase name="General error">
     <failure type="ERROR" message="first generic error" />
   </testcase>
@@ -104,17 +104,17 @@ public function dataFormatterOutputProvider(): Generator
 			4,
 			2,
 			'<?xml version="1.0" encoding="UTF-8"?>
-<testsuite failures="6" name="phpstan" tests="6" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/junit-team/junit5/r5.5.1/platform-tests/src/test/resources/jenkins-junit.xsd">
-  <testcase name="folder with unicode &#x1F603;/file name with &quot;spaces&quot; and unicode &#x1F603;.php:2">
+<testsuite failures="6" name="phpstan" tests="6">
+  <testcase name="folder with unicode &#x1F603;/file name with &quot;spaces&quot; and unicode &#x1F603;.php:2" file="folder with unicode &#x1F603;/file name with &quot;spaces&quot; and unicode &#x1F603;.php" line="2">
     <failure type="ERROR" message="Bar Bar2" />
   </testcase>
-  <testcase name="folder with unicode &#x1F603;/file name with &quot;spaces&quot; and unicode &#x1F603;.php:4">
+  <testcase name="folder with unicode &#x1F603;/file name with &quot;spaces&quot; and unicode &#x1F603;.php:4" file="folder with unicode &#x1F603;/file name with &quot;spaces&quot; and unicode &#x1F603;.php" line="4">
     <failure type="ERROR" message="Foo" />
   </testcase>
-  <testcase name="foo.php:1">
+  <testcase name="foo.php:1" file="foo.php" line="1">
     <failure type="ERROR" message="Foo"/>
   </testcase>
-  <testcase name="foo.php:5">
+  <testcase name="foo.php:5" file="foo.php" line="5">
     <failure type="ERROR" message="Bar Bar2"/>
   </testcase>
   <testcase name="General error">
@@ -152,11 +152,6 @@ public function testFormatErrors(
 		$xml = new DOMDocument();
 		$xml->loadXML($this->getOutputContent());
 
-		$this->assertTrue(
-			$xml->schemaValidate(__DIR__ . '/junit-schema.xsd'),
-			'Schema do not validate',
-		);
-
 		$this->assertXmlStringEqualsXmlString(
 			$expected,
 			$this->getOutputContent(),
diff --git a/tests/PHPStan/Command/ErrorFormatter/junit-schema.xsd b/tests/PHPStan/Command/ErrorFormatter/junit-schema.xsd
deleted file mode 100644
index b9b70088a0..0000000000
--- a/tests/PHPStan/Command/ErrorFormatter/junit-schema.xsd
+++ /dev/null
@@ -1,118 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
- Source: https://svn.jenkins-ci.org/trunk/hudson/dtkit/dtkit-format/dtkit-junit-model/src/main/resources/com/thalesgroup/dtkit/junit/model/xsd/junit-4.xsd
-
- This file available under the terms of the MIT License as follows:
-
- *******************************************************************************
- * Copyright (c) 2010 Thales Corporate Services SAS                             *
- *                                                                              *
- * Permission is hereby granted, free of charge, to any person obtaining a copy *
- * of this software and associated documentation files (the "Software"), to deal*
- * in the Software without restriction, including without limitation the rights *
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell    *
- * copies of the Software, and to permit persons to whom the Software is        *
- * furnished to do so, subject to the following conditions:                     *
- *                                                                              *
- * The above copyright notice and this permission notice shall be included in   *
- * all copies or substantial portions of the Software.                          *
- *                                                                              *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR   *
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,     *
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  *
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER       *
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,*
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN    *
- * THE SOFTWARE.                                                                *
- ********************************************************************************
- -->
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
-
-	<xs:element name="failure">
-		<xs:complexType mixed="true">
-			<xs:attribute name="type" type="xs:string" use="optional"/>
-			<xs:attribute name="message" type="xs:string" use="optional"/>
-		</xs:complexType>
-	</xs:element>
-
-	<xs:element name="error">
-		<xs:complexType mixed="true">
-			<xs:attribute name="type" type="xs:string" use="optional"/>
-			<xs:attribute name="message" type="xs:string" use="optional"/>
-		</xs:complexType>
-	</xs:element>
-
-	<xs:element name="properties">
-		<xs:complexType>
-			<xs:sequence>
-				<xs:element ref="property" maxOccurs="unbounded"/>
-			</xs:sequence>
-		</xs:complexType>
-	</xs:element>
-
-	<xs:element name="property">
-		<xs:complexType>
-			<xs:attribute name="name" type="xs:string" use="required"/>
-			<xs:attribute name="value" type="xs:string" use="required"/>
-		</xs:complexType>
-	</xs:element>
-
-	<xs:element name="skipped" type="xs:string"/>
-	<xs:element name="system-err" type="xs:string"/>
-	<xs:element name="system-out" type="xs:string"/>
-
-	<xs:element name="testcase">
-		<xs:complexType>
-			<xs:sequence>
-				<xs:element ref="skipped" minOccurs="0" maxOccurs="1"/>
-				<xs:element ref="error" minOccurs="0" maxOccurs="unbounded"/>
-				<xs:element ref="failure" minOccurs="0" maxOccurs="unbounded"/>
-				<xs:element ref="system-out" minOccurs="0" maxOccurs="unbounded"/>
-				<xs:element ref="system-err" minOccurs="0" maxOccurs="unbounded"/>
-			</xs:sequence>
-			<xs:attribute name="name" type="xs:string" use="required"/>
-			<xs:attribute name="assertions" type="xs:string" use="optional"/>
-			<xs:attribute name="time" type="xs:string" use="optional"/>
-			<xs:attribute name="classname" type="xs:string" use="optional"/>
-			<xs:attribute name="status" type="xs:string" use="optional"/>
-		</xs:complexType>
-	</xs:element>
-
-	<xs:element name="testsuite">
-		<xs:complexType>
-			<xs:sequence>
-				<xs:element ref="properties" minOccurs="0" maxOccurs="1"/>
-				<xs:element ref="testcase" minOccurs="0" maxOccurs="unbounded"/>
-				<xs:element ref="system-out" minOccurs="0" maxOccurs="1"/>
-				<xs:element ref="system-err" minOccurs="0" maxOccurs="1"/>
-			</xs:sequence>
-			<xs:attribute name="name" type="xs:string" use="required"/>
-			<xs:attribute name="tests" type="xs:string" use="required"/>
-			<xs:attribute name="failures" type="xs:string" use="optional"/>
-			<xs:attribute name="errors" type="xs:string" use="optional"/>
-			<xs:attribute name="time" type="xs:string" use="optional"/>
-			<xs:attribute name="disabled" type="xs:string" use="optional"/>
-			<xs:attribute name="skipped" type="xs:string" use="optional"/>
-			<xs:attribute name="timestamp" type="xs:string" use="optional"/>
-			<xs:attribute name="hostname" type="xs:string" use="optional"/>
-			<xs:attribute name="id" type="xs:string" use="optional"/>
-			<xs:attribute name="package" type="xs:string" use="optional"/>
-		</xs:complexType>
-	</xs:element>
-
-	<xs:element name="testsuites">
-		<xs:complexType>
-			<xs:sequence>
-				<xs:element ref="testsuite" minOccurs="0" maxOccurs="unbounded"/>
-			</xs:sequence>
-			<xs:attribute name="name" type="xs:string" use="optional"/>
-			<xs:attribute name="time" type="xs:string" use="optional"/>
-			<xs:attribute name="tests" type="xs:string" use="optional"/>
-			<xs:attribute name="failures" type="xs:string" use="optional"/>
-			<xs:attribute name="disabled" type="xs:string" use="optional"/>
-			<xs:attribute name="errors" type="xs:string" use="optional"/>
-		</xs:complexType>
-	</xs:element>
-
-
-</xs:schema>
