Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
36.84% covered (danger)
36.84%
14 / 38
14.29% covered (danger)
14.29%
1 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
PhpUnitXml
36.84% covered (danger)
36.84%
14 / 38
14.29% covered (danger)
14.29%
1 / 7
120.77
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isPhpUnitXmlPrepared
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 containsSplitGroups
87.50% covered (warning)
87.50%
7 / 8
0.00% covered (danger)
0.00%
0 / 1
6.07
 addSplitGroups
75.00% covered (warning)
75.00%
6 / 8
0.00% covered (danger)
0.00%
0 / 1
4.25
 getSplitGroupSuite
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
20
 addSpecialCaseTests
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 saveToDisk
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3declare( strict_types = 1 );
4
5namespace MediaWiki\Composer\PhpUnitSplitter;
6
7use DOMDocument;
8use SimpleXMLElement;
9
10/**
11 * @license GPL-2.0-or-later
12 */
13class PhpUnitXml {
14
15    public const PHP_UNIT_XML_FILE = "phpunit.xml";
16
17    private SimpleXMLElement $xml;
18
19    public function __construct( string $phpUnitXmlFile ) {
20        $this->xml = new SimpleXMLElement( file_get_contents( $phpUnitXmlFile ) );
21    }
22
23    public static function isPhpUnitXmlPrepared( string $targetFile ): bool {
24        if ( !file_exists( $targetFile ) ) {
25            return false;
26        }
27        $unitFile = new PhpUnitXml( $targetFile );
28        return $unitFile->containsSplitGroups();
29    }
30
31    public function containsSplitGroups(): bool {
32        if ( !property_exists( $this->xml, "testsuites" ) ||
33            !property_exists( $this->xml->testsuites, "testsuite" ) ) {
34            return false;
35        }
36        foreach ( $this->xml->testsuites->testsuite as $child ) {
37            if ( isset( $child->attributes()["name"] ) &&
38                strpos( (string)$child->attributes()["name"], "split_group_" ) === 0 ) {
39                return true;
40            }
41        }
42        return false;
43    }
44
45    public function addSplitGroups( array $splitGroups ) {
46        $groups = count( $splitGroups );
47        for ( $i = 0; $i < $groups; $i++ ) {
48            $suite = $this->xml->testsuites->addChild( "testsuite" );
49            $suite->addAttribute( "name", "split_group_" . $i );
50            $group = $splitGroups[$i];
51            if ( !empty( $group["list"] ) ) {
52                foreach ( $group["list"] as $file ) {
53                    $suite->addChild( "file", $file );
54                }
55            }
56        }
57    }
58
59    /**
60     * @throws SuiteGenerationException
61     */
62    private function getSplitGroupSuite( int $groupId ): SimpleXMLElement {
63        foreach ( $this->xml->testsuites->testsuite as $child ) {
64            if ( isset( $child->attributes()["name"] ) &&
65                (string)$child->attributes()["name"] === "split_group_" . $groupId ) {
66                return $child;
67            }
68        }
69        throw new SuiteGenerationException( $groupId );
70    }
71
72    /**
73     * There are some tests suites / classes where the test listing does not work because test
74     * cases are generated dynamically. For this special cases, we need to add the classes
75     * manually back into the suites list to ensure that they get included in a test run.
76     * @see T345481
77     * @see T358394
78     * @throws SuiteGenerationException
79     */
80    public function addSpecialCaseTests( int $groupCount ) {
81        $suite = $this->xml->testsuites->addChild( "testsuite" );
82        $suite->addAttribute( "name", "split_group_" . ( $groupCount - 1 ) );
83        $suite->addChild( "file", "tests/phpunit/suites/ExtensionsParserTestSuite.php" );
84
85        $sandboxTest = "extensions/Scribunto/tests/phpunit/Engines/LuaSandbox/SandboxTest.php";
86        if ( file_exists( $sandboxTest ) ) {
87            $suite = $this->getSplitGroupSuite( 0 );
88            $suite->addChild( "file", $sandboxTest );
89        }
90    }
91
92    public function saveToDisk( string $targetXml ) {
93        $dom = new DOMDocument( '1.0' );
94        $dom->preserveWhiteSpace = false;
95        $dom->formatOutput = true;
96        $dom->loadXML( $this->xml->asXML() );
97        file_put_contents( $targetXml, $dom->saveXML() );
98    }
99
100}