File: TestSuiteBuilder.php

package info (click to toggle)
mediawiki 1%3A1.43.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 417,464 kB
  • sloc: php: 1,062,949; javascript: 664,290; sql: 9,714; python: 5,458; xml: 3,489; sh: 1,131; makefile: 64
file content (61 lines) | stat: -rw-r--r-- 1,960 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<?php

declare( strict_types = 1 );

namespace MediaWiki\Composer\PhpUnitSplitter;

/**
 * @license GPL-2.0-or-later
 */
class TestSuiteBuilder {

	private static function sortByTimeDescending( TestDescriptor $a, TestDescriptor $b ): int {
		if ( $a->getDuration() === $b->getDuration() ) {
			return 0;
		}
		return ( $a->getDuration() > $b->getDuration() ? -1 : 1 );
	}

	private static function smallestGroup( array $suites ): int {
		$min = 10000;
		$minIndex = 0;
		$groups = count( $suites );
		for ( $i = 0; $i < $groups; $i++ ) {
			if ( $suites[$i]["time"] < $min ) {
				$min = $suites[$i]["time"];
				$minIndex = $i;
			}
		}
		return $minIndex;
	}

	public function buildSuites( array $testDescriptors, int $groups ): array {
		$suites = array_fill( 0, $groups, [ "list" => [], "time" => 0 ] );
		$roundRobin = 0;
		usort( $testDescriptors, [ self::class, "sortByTimeDescending" ] );
		foreach ( $testDescriptors as $testDescriptor ) {
			if ( !$testDescriptor->getFilename() ) {
				// We didn't resolve a matching file for this test, so we skip it
				// from the suite here. This only happens for "known" missing test
				// classes (see PhpUnitXmlManager::EXPECTED_MISSING_CLASSES) - in
				// all other cases a missing test file will throw an exception during
				// suite building.
				continue;
			}
			if ( $testDescriptor->getDuration() === 0 ) {
				// If no explicit timing information is available for a test, we just
				// drop it round-robin into the next bucket.
				$nextSuite = $roundRobin;
				$roundRobin = ( $roundRobin + 1 ) % $groups;
			} else {
				// If we have information about the test duration, we try and balance
				// out the tests suites by having an even amount of time spent on
				// each suite.
				$nextSuite = self::smallestGroup( $suites );
			}
			$suites[$nextSuite]["list"][] = $testDescriptor->getFilename();
			$suites[$nextSuite]["time"] += $testDescriptor->getDuration();
		}
		return $suites;
	}
}