All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.liferay.jenkins.results.parser.test.clazz.group.BatchTestClassGroup Maven / Gradle / Ivy

The newest version!
/**
 * SPDX-FileCopyrightText: (c) 2000 Liferay, Inc. https://liferay.com
 * SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
 */

package com.liferay.jenkins.results.parser.test.clazz.group;

import com.google.common.collect.Lists;

import com.liferay.jenkins.results.parser.BatchHistory;
import com.liferay.jenkins.results.parser.JenkinsMaster;
import com.liferay.jenkins.results.parser.JenkinsResultsParserUtil;
import com.liferay.jenkins.results.parser.Job;
import com.liferay.jenkins.results.parser.JobHistory;
import com.liferay.jenkins.results.parser.PortalGitWorkingDirectory;
import com.liferay.jenkins.results.parser.PortalTestClassJob;
import com.liferay.jenkins.results.parser.RootCauseAnalysisToolJob;
import com.liferay.jenkins.results.parser.TestHistory;
import com.liferay.jenkins.results.parser.TestSuiteJob;
import com.liferay.jenkins.results.parser.TestTaskHistory;
import com.liferay.jenkins.results.parser.job.property.GlobJobProperty;
import com.liferay.jenkins.results.parser.job.property.JobProperty;
import com.liferay.jenkins.results.parser.job.property.JobPropertyFactory;
import com.liferay.jenkins.results.parser.test.clazz.TestClass;

import java.io.File;
import java.io.IOException;

import java.nio.file.PathMatcher;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;

import org.json.JSONArray;
import org.json.JSONObject;

/**
 * @author Michael Hashimoto
 */
public abstract class BatchTestClassGroup extends BaseTestClassGroup {

	public void addAxisTestClassGroup(AxisTestClassGroup axisTestClassGroup) {
		axisTestClassGroups.add(axisTestClassGroup);
	}

	public void addSegmentTestClassGroup(
		SegmentTestClassGroup segmentTestClassGroup) {

		_segmentTestClassGroups.add(segmentTestClassGroup);
	}

	public long getAverageTestDuration(String testName) {
		if (_averageTestDurations.containsKey(testName)) {
			return _averageTestDurations.get(testName);
		}

		long averageTestDuration = _getDefaultTestDuration();

		BatchHistory batchHistory = getBatchHistory();

		if (batchHistory != null) {
			TestHistory testHistory = batchHistory.getTestHistory(testName);

			if (testHistory != null) {
				averageTestDuration = testHistory.getAverageDuration();
			}
		}

		_averageTestDurations.put(testName, averageTestDuration);

		return averageTestDuration;
	}

	public long getAverageTestOverheadDuration(String testName) {
		if (_averageTestOverheadDurations.containsKey(testName)) {
			return _averageTestOverheadDurations.get(testName);
		}

		long averageTestOverheadDuration = _getDefaultTestOverheadDuration();

		BatchHistory batchHistory = getBatchHistory();

		if (batchHistory != null) {
			TestHistory testHistory = batchHistory.getTestHistory(testName);

			if (testHistory != null) {
				averageTestOverheadDuration =
					testHistory.getAverageOverheadDuration();
			}
		}

		_averageTestOverheadDurations.put(
			testName, averageTestOverheadDuration);

		return averageTestOverheadDuration;
	}

	public long getAverageTestTaskDuration(String testName) {
		TestTaskHistory testTaskHistory = _getTestTaskHistory(testName);

		if (testTaskHistory == null) {
			return _getDefaultTestTaskDuration();
		}

		long averageDuration = testTaskHistory.getAverageDuration();

		if (averageDuration == 0) {
			return _getDefaultTestTaskDuration();
		}

		return averageDuration;
	}

	public int getAxisCount() {
		if (ignore()) {
			return 0;
		}

		JobProperty jobProperty = getJobProperty("test.batch.axis.count");

		String jobPropertyValue = jobProperty.getValue();

		if (JenkinsResultsParserUtil.isInteger(jobPropertyValue)) {
			recordJobProperty(jobProperty);

			return Integer.parseInt(jobPropertyValue);
		}

		int testClassCount = testClasses.size();

		if (testClassCount == 0) {
			return 0;
		}

		int axisMaxSize = getAxisMaxSize();

		if (axisMaxSize <= 0) {
			throw new RuntimeException(
				"'test.batch.axis.max.size' cannot be 0 or less");
		}

		return (int)Math.ceil((double)testClassCount / axisMaxSize);
	}

	public AxisTestClassGroup getAxisTestClassGroup(int axisId) {
		return axisTestClassGroups.get(axisId);
	}

	public List getAxisTestClassGroups() {
		return axisTestClassGroups;
	}

	public BatchHistory getBatchHistory() {
		if (_batchHistory != null) {
			return _batchHistory;
		}

		Job job = getJob();

		JobHistory jobHistory = job.getJobHistory();

		if (jobHistory == null) {
			return null;
		}

		_batchHistory = jobHistory.getBatchHistory(getBatchName());

		return _batchHistory;
	}

	public String getBatchJobName() {
		String topLevelJobName = portalTestClassJob.getJobName();

		Matcher jobNameMatcher = _jobNamePattern.matcher(topLevelJobName);

		String batchJobSuffix = "-batch";

		String slaveLabel = getSlaveLabel();

		if (slaveLabel.contains("win")) {
			batchJobSuffix = "-windows-batch";
		}

		if (jobNameMatcher.find()) {
			return JenkinsResultsParserUtil.combine(
				jobNameMatcher.group("jobBaseName"), batchJobSuffix,
				jobNameMatcher.group("jobVariant"));
		}

		return topLevelJobName + batchJobSuffix;
	}

	public String getBatchName() {
		return batchName;
	}

	public String getCohortName() {
		JobProperty jobProperty = getJobProperty("test.batch.cohort.name");

		String jobPropertyValue = jobProperty.getValue();

		if (!JenkinsResultsParserUtil.isNullOrEmpty(jobPropertyValue)) {
			recordJobProperty(jobProperty);

			return jobPropertyValue;
		}

		jobPropertyValue = JenkinsResultsParserUtil.getCohortName();

		if (!JenkinsResultsParserUtil.isNullOrEmpty(jobPropertyValue)) {
			return jobPropertyValue;
		}

		return "test-1";
	}

	public String getDownstreamJobName() {
		String topLevelJobName = portalTestClassJob.getJobName();

		Matcher jobNameMatcher = _jobNamePattern.matcher(topLevelJobName);

		String batchJobSuffix = "-downstream";

		String slaveLabel = getSlaveLabel();

		if (slaveLabel.contains("win")) {
			batchJobSuffix = "-windows-downstream";
		}

		if (jobNameMatcher.find()) {
			return JenkinsResultsParserUtil.combine(
				jobNameMatcher.group("jobBaseName"), batchJobSuffix,
				jobNameMatcher.group("jobVariant"));
		}

		return topLevelJobName + batchJobSuffix;
	}

	@Override
	public Job getJob() {
		return portalTestClassJob;
	}

	public JSONObject getJSONObject() {
		if (jsonObject != null) {
			return jsonObject;
		}

		jsonObject = new JSONObject();

		jsonObject.put(
			"batch_name", getBatchName()
		).put(
			"include_stable_test_suite", includeStableTestSuite
		).put(
			"job_properties", _getJobPropertiesMap()
		);

		JSONArray segmentJSONArray = new JSONArray();

		for (SegmentTestClassGroup segmentTestClassGroup :
				getSegmentTestClassGroups()) {

			segmentJSONArray.put(segmentTestClassGroup.getJSONObject());
		}

		jsonObject.put(
			"segments", segmentJSONArray
		).put(
			"test_hotfix_changes", testHotfixChanges
		).put(
			"test_release_bundle", testReleaseBundle
		).put(
			"test_relevant_changes", testRelevantChanges
		).put(
			"test_relevant_changes_in_stable", testRelevantChangesInStable
		).put(
			"test_relevant_junit_tests_only", testRelevantJUnitTestsOnly
		).put(
			"test_relevant_junit_tests_only_in_stable",
			testRelevantJUnitTestsOnlyInStable
		);

		return jsonObject;
	}

	public Integer getMaximumSlavesPerHost() {
		JobProperty jobProperty = getJobProperty(
			"test.batch.maximum.slaves.per.host");

		String jobPropertyValue = jobProperty.getValue();

		if (JenkinsResultsParserUtil.isInteger(jobPropertyValue)) {
			recordJobProperty(jobProperty);

			return Integer.valueOf(jobPropertyValue);
		}

		return JenkinsMaster.getSlavesPerHostDefault();
	}

	public Integer getMinimumSlaveRAM() {
		JobProperty jobProperty = getJobProperty(
			"test.batch.minimum.slave.ram");

		String jobPropertyValue = jobProperty.getValue();

		if (JenkinsResultsParserUtil.isInteger(jobPropertyValue)) {
			recordJobProperty(jobProperty);

			return Integer.valueOf(jobPropertyValue);
		}

		return JenkinsMaster.getSlaveRAMMinimumDefault();
	}

	public PortalGitWorkingDirectory getPortalGitWorkingDirectory() {
		return portalGitWorkingDirectory;
	}

	public int getSegmentCount() {
		return _segmentTestClassGroups.size();
	}

	public SegmentTestClassGroup getSegmentTestClassGroup(int segmentId) {
		if ((_segmentTestClassGroups.size() - 1) < segmentId) {
			return null;
		}

		return _segmentTestClassGroups.get(segmentId);
	}

	public List getSegmentTestClassGroups() {
		return _segmentTestClassGroups;
	}

	public String getSlaveLabel() {
		JobProperty jobProperty = getJobProperty("test.batch.slave.label");

		String jobPropertyValue = jobProperty.getValue();

		if (jobPropertyValue != null) {
			recordJobProperty(jobProperty);

			return jobPropertyValue;
		}

		return SLAVE_LABEL_DEFAULT;
	}

	public String getTestCasePropertiesContent() {
		StringBuilder sb = new StringBuilder();

		for (SegmentTestClassGroup segmentTestClassGroup :
				getSegmentTestClassGroups()) {

			sb.append(segmentTestClassGroup.getTestCasePropertiesContent());
			sb.append("\n");
		}

		return sb.toString();
	}

	public String getTestTaskName(String testName) {
		TestTaskHistory testTaskHistory = _getTestTaskHistory(testName);

		if (testTaskHistory == null) {
			return null;
		}

		return testTaskHistory.getTestTaskName();
	}

	public boolean testAnalyticsCloud() {
		if (_testAnalyticsCloud != null) {
			return _testAnalyticsCloud;
		}

		for (SegmentTestClassGroup segmentTestClassGroup :
				getSegmentTestClassGroups()) {

			if (segmentTestClassGroup.testAnalyticsCloud()) {
				_testAnalyticsCloud = true;

				return _testAnalyticsCloud;
			}
		}

		_testAnalyticsCloud = false;

		return _testAnalyticsCloud;
	}

	protected BatchTestClassGroup(
		JSONObject jsonObject, PortalTestClassJob portalTestClassJob) {

		this.jsonObject = jsonObject;
		this.portalTestClassJob = portalTestClassJob;

		batchName = jsonObject.getString("batch_name");

		includeStableTestSuite = jsonObject.getBoolean(
			"include_stable_test_suite");

		portalGitWorkingDirectory =
			portalTestClassJob.getPortalGitWorkingDirectory();

		JSONArray segmentsJSONArray = jsonObject.optJSONArray("segments");

		if ((segmentsJSONArray != null) && !segmentsJSONArray.isEmpty()) {
			for (int i = 0; i < segmentsJSONArray.length(); i++) {
				JSONObject segmentJSONObject = segmentsJSONArray.getJSONObject(
					i);

				_segmentTestClassGroups.add(
					TestClassGroupFactory.newSegmentTestClassGroup(
						this, segmentJSONObject));
			}
		}

		testHotfixChanges = jsonObject.optBoolean("test_hotfix_changes");
		testRelevantChanges = jsonObject.optBoolean("test_relevant_changes");
		testReleaseBundle = jsonObject.optBoolean("test_release_bundle");
		testRelevantJUnitTestsOnly = jsonObject.optBoolean(
			"test_relevant_junit_tests_only");
		testRelevantJUnitTestsOnlyInStable = jsonObject.optBoolean(
			"test_relevant_junit_tests_only_in_stable");

		if (portalTestClassJob instanceof TestSuiteJob) {
			TestSuiteJob testSuiteJob = (TestSuiteJob)portalTestClassJob;

			testSuiteName = testSuiteJob.getTestSuiteName();
		}
		else {
			testSuiteName = null;
		}
	}

	protected BatchTestClassGroup(
		String batchName, PortalTestClassJob portalTestClassJob) {

		this.batchName = batchName;
		this.portalTestClassJob = portalTestClassJob;

		portalGitWorkingDirectory =
			portalTestClassJob.getPortalGitWorkingDirectory();

		if (portalTestClassJob instanceof TestSuiteJob) {
			TestSuiteJob testSuiteJob = (TestSuiteJob)portalTestClassJob;

			testSuiteName = testSuiteJob.getTestSuiteName();
		}
		else {
			testSuiteName = null;
		}

		_setTestHotfixChanges();
		_setTestReleaseBundle();
		_setTestRelevantChanges();
		_setTestRelevantChangesInStable();

		_setTestRelevantJUnitTestsOnly();
		_setTestRelevantJUnitTestsOnlyInStable();

		_setIncludeStableTestSuite();
	}

	protected int getAxisMaxSize() {
		JobProperty jobProperty = getJobProperty("test.batch.axis.max.size");

		String jobPropertyValue = jobProperty.getValue();

		if (JenkinsResultsParserUtil.isInteger(jobPropertyValue)) {
			recordJobProperty(jobProperty);

			return Integer.parseInt(jobPropertyValue);
		}

		return AXES_SIZE_MAX_DEFAULT;
	}

	protected List getGlobs(List jobProperties) {
		List globs = new ArrayList<>();

		for (JobProperty jobProperty : jobProperties) {
			if (!(jobProperty instanceof GlobJobProperty)) {
				continue;
			}

			GlobJobProperty globJobProperty = (GlobJobProperty)jobProperty;

			for (String relativeGlob : globJobProperty.getRelativeGlobs()) {
				if ((relativeGlob == null) || globs.contains(relativeGlob)) {
					continue;
				}

				globs.add(relativeGlob);
			}
		}

		Collections.sort(globs);

		return globs;
	}

	protected List getJobProperties(
		File file, String basePropertyName, JobProperty.Type jobType,
		Set traversedPropertyFileSet) {

		List jobPropertiesList = new ArrayList<>();

		File modulesBaseDir = new File(
			portalGitWorkingDirectory.getWorkingDirectory(), "modules");

		if ((file == null) || file.equals(modulesBaseDir) ||
			JenkinsResultsParserUtil.isPoshiFile(file)) {

			return jobPropertiesList;
		}

		if (!file.isDirectory()) {
			file = file.getParentFile();
		}

		File testPropertiesFile = new File(file, "test.properties");

		if (traversedPropertyFileSet == null) {
			traversedPropertyFileSet = new HashSet<>();
		}

		if (testPropertiesFile.exists() &&
			!traversedPropertyFileSet.contains(testPropertiesFile)) {

			JobProperty jobProperty = getJobProperty(
				basePropertyName, file, jobType);

			String jobPropertyValue = jobProperty.getValue();

			if (!JenkinsResultsParserUtil.isNullOrEmpty(jobPropertyValue) &&
				!jobPropertiesList.contains(jobProperty)) {

				jobPropertiesList.add(jobProperty);
			}

			traversedPropertyFileSet.add(testPropertiesFile);
		}

		JobProperty ignoreParentsJobProperty = getJobProperty(
			"ignoreParents[" + getTestSuiteName() + "]", file,
			JobProperty.Type.MODULE_TEST_DIR);

		boolean ignoreParents = Boolean.valueOf(
			ignoreParentsJobProperty.getValue());

		if (ignoreParents) {
			return jobPropertiesList;
		}

		jobPropertiesList.addAll(
			getJobProperties(
				file.getParentFile(), basePropertyName, jobType,
				traversedPropertyFileSet));

		return jobPropertiesList;
	}

	protected JobProperty getJobProperty(String basePropertyName) {
		return _getJobProperty(basePropertyName, null, null, null, null, true);
	}

	protected JobProperty getJobProperty(
		String basePropertyName, File testBaseDir, JobProperty.Type type) {

		return _getJobProperty(
			basePropertyName, null, null, testBaseDir, type, true);
	}

	protected JobProperty getJobProperty(
		String basePropertyName, File testBaseDir, JobProperty.Type type,
		boolean useBasePropertyName) {

		return _getJobProperty(
			basePropertyName, null, null, testBaseDir, type,
			useBasePropertyName);
	}

	protected JobProperty getJobProperty(
		String basePropertyName, JobProperty.Type type) {

		return _getJobProperty(basePropertyName, null, null, null, type, true);
	}

	protected JobProperty getJobProperty(
		String basePropertyName, String testSuiteName, File testBaseDir,
		JobProperty.Type type) {

		return _getJobProperty(
			basePropertyName, testSuiteName, null, testBaseDir, type, true);
	}

	protected JobProperty getJobProperty(
		String basePropertyName, String testSuiteName, String testBatchName) {

		return _getJobProperty(
			basePropertyName, testSuiteName, testBatchName, null, null, true);
	}

	protected JobProperty getJobProperty(
		String basePropertyName, String testSuiteName, String testBatchName,
		File testBaseDir, JobProperty.Type type) {

		return _getJobProperty(
			basePropertyName, testSuiteName, testBatchName, testBaseDir, type,
			true);
	}

	protected JobProperty getJobProperty(
		String basePropertyName, String testSuiteName, String testBatchName,
		JobProperty.Type type) {

		return _getJobProperty(
			basePropertyName, testSuiteName, testBatchName, null, type, true);
	}

	protected JobProperty getJobProperty(
		String basePropertyName, String testSuiteName, String testBatchName,
		String ruleName, File testBaseDir, JobProperty.Type type) {

		return _getJobProperty(
			basePropertyName, testSuiteName, testBatchName, ruleName,
			testBaseDir, type, true);
	}

	protected List getPathMatchers(
		List jobProperties) {

		List pathMatchers = new ArrayList<>();

		for (JobProperty jobProperty : jobProperties) {
			if (!(jobProperty instanceof GlobJobProperty)) {
				continue;
			}

			GlobJobProperty globJobProperty = (GlobJobProperty)jobProperty;

			List globPathMatchers =
				globJobProperty.getPathMatchers();

			if (globPathMatchers == null) {
				continue;
			}

			for (PathMatcher globPathMatcher : globPathMatchers) {
				if ((globPathMatcher == null) ||
					pathMatchers.contains(globPathMatcher)) {

					continue;
				}

				pathMatchers.add(globPathMatcher);
			}
		}

		return pathMatchers;
	}

	protected List getPathMatchers(
		String relativeGlobs, File workingDirectory) {

		if ((relativeGlobs == null) || relativeGlobs.isEmpty()) {
			return Collections.emptyList();
		}

		return JenkinsResultsParserUtil.toPathMatchers(
			JenkinsResultsParserUtil.getCanonicalPath(workingDirectory) +
				File.separator,
			JenkinsResultsParserUtil.getGlobsFromProperty(relativeGlobs));
	}

	protected List getRelevantIntegrationUnitBatchNames() {
		List relevantIntegrationUnitBatchNames = new ArrayList<>();

		if (!testSuiteName.equals("relevant")) {
			return relevantIntegrationUnitBatchNames;
		}

		JobProperty jobProperty = getJobProperty("test.batch.names");

		String jobPropertyValue = jobProperty.getValue();

		if (JenkinsResultsParserUtil.isNullOrEmpty(jobPropertyValue)) {
			return relevantIntegrationUnitBatchNames;
		}

		for (String relevantTestBatchName : jobPropertyValue.split(",")) {
			if (relevantTestBatchName.startsWith("integration-") ||
				relevantTestBatchName.startsWith("modules-integration") ||
				relevantTestBatchName.startsWith("modules-unit") ||
				relevantTestBatchName.startsWith("unit-")) {

				relevantIntegrationUnitBatchNames.add(relevantTestBatchName);
			}
		}

		return relevantIntegrationUnitBatchNames;
	}

	protected List getRequiredModuleDirs(List moduleDirs) {
		return _getRequiredModuleDirs(moduleDirs, new ArrayList<>(moduleDirs));
	}

	protected int getSegmentMaxChildren() {
		JobProperty jobProperty = getJobProperty(
			"test.batch.segment.max.children");

		String jobPropertyValue = jobProperty.getValue();

		if (JenkinsResultsParserUtil.isInteger(jobPropertyValue)) {
			recordJobProperty(jobProperty);

			return Integer.valueOf(jobPropertyValue);
		}

		return _SEGMENT_MAX_CHILDREN_DEFAULT;
	}

	protected long getTargetAxisDuration() {
		JobProperty jobProperty = getJobProperty(
			"test.batch.target.axis.duration");

		String jobPropertyValue = jobProperty.getValue();

		if ((jobPropertyValue == null) || !jobPropertyValue.matches("\\d+")) {
			return 0L;
		}

		recordJobProperty(jobProperty);

		return Long.parseLong(jobPropertyValue);
	}

	protected String getTestSuiteName() {
		return testSuiteName;
	}

	protected boolean ignore() {
		if (!isStableTestSuiteBatch() && testRelevantJUnitTestsOnly) {
			return true;
		}

		if (isStableTestSuiteBatch() && testRelevantJUnitTestsOnlyInStable) {
			return true;
		}

		return false;
	}

	protected boolean isRootCauseAnalysis() {
		return getJob() instanceof RootCauseAnalysisToolJob;
	}

	protected boolean isStableTestSuiteBatch() {
		return isStableTestSuiteBatch(batchName);
	}

	protected boolean isStableTestSuiteBatch(String batchName) {
		List testBatchNames = new ArrayList<>();

		JobProperty jobProperty = getJobProperty("test.batch.names[stable]");

		String jobPropertyValue = jobProperty.getValue();

		if (jobPropertyValue != null) {
			Collections.addAll(testBatchNames, jobPropertyValue.split(","));
		}

		if (testBatchNames.contains(batchName)) {
			return true;
		}

		return false;
	}

	protected void recordJobProperties(List jobProperties) {
		for (JobProperty jobProperty : jobProperties) {
			recordJobProperty(jobProperty);
		}
	}

	protected void recordJobProperty(JobProperty jobProperty) {
		if ((jobProperty == null) || (jobProperty.getValue() == null) ||
			_jobProperties.contains(jobProperty)) {

			return;
		}

		_jobProperties.add(jobProperty);
	}

	protected void setAxisTestClassGroups() {
		int testClassCount = testClasses.size();

		if (testClassCount == 0) {
			return;
		}

		int axisCount = getAxisCount();

		int axisSize = (int)Math.ceil((double)testClassCount / axisCount);

		for (List axisTestClasses :
				Lists.partition(testClasses, axisSize)) {

			AxisTestClassGroup axisTestClassGroup =
				TestClassGroupFactory.newAxisTestClassGroup(this);

			for (TestClass axisTestClass : axisTestClasses) {
				axisTestClassGroup.addTestClass(axisTestClass);
			}

			axisTestClassGroups.add(axisTestClassGroup);
		}
	}

	protected void setSegmentTestClassGroups() {
		if (!_segmentTestClassGroups.isEmpty() ||
			axisTestClassGroups.isEmpty()) {

			return;
		}

		List> axisTestClassGroupsList =
			new ArrayList<>();

		axisTestClassGroupsList.add(axisTestClassGroups);

		axisTestClassGroupsList = _partitionByMinimumSlaveRAM(
			axisTestClassGroupsList);
		axisTestClassGroupsList = _partitionBySlaveLabel(
			axisTestClassGroupsList);
		axisTestClassGroupsList = _partitionByTestBaseDir(
			axisTestClassGroupsList);

		axisTestClassGroupsList = _partitionByMaxChildren(
			axisTestClassGroupsList);

		for (List axisTestClassGroups :
				axisTestClassGroupsList) {

			SegmentTestClassGroup segmentTestClassGroup =
				TestClassGroupFactory.newSegmentTestClassGroup(this);

			for (AxisTestClassGroup axisTestClassGroup : axisTestClassGroups) {
				segmentTestClassGroup.addAxisTestClassGroup(axisTestClassGroup);
			}

			_segmentTestClassGroups.add(segmentTestClassGroup);
		}
	}

	protected static final int AXES_SIZE_MAX_DEFAULT = 5000;

	protected static final String NAME_STABLE_TEST_SUITE = "stable";

	protected static final String SLAVE_LABEL_DEFAULT = "!master";

	protected final List axisTestClassGroups =
		new ArrayList<>();
	protected final String batchName;
	protected boolean includeStableTestSuite;
	protected JSONObject jsonObject;
	protected final PortalGitWorkingDirectory portalGitWorkingDirectory;
	protected final PortalTestClassJob portalTestClassJob;
	protected boolean testHotfixChanges;
	protected boolean testReleaseBundle;
	protected boolean testRelevantChanges;
	protected boolean testRelevantChangesInStable;
	protected boolean testRelevantJUnitTestsOnly;
	protected boolean testRelevantJUnitTestsOnlyInStable;
	protected final String testSuiteName;

	protected static final class CSVReport {

		public CSVReport(Row headerRow) {
			if (headerRow == null) {
				throw new IllegalArgumentException("headerRow is null");
			}

			_csvReportRows.add(headerRow);
		}

		public void addRow(Row csvReportRow) {
			Row headerRow = _csvReportRows.get(0);

			if (csvReportRow.size() != headerRow.size()) {
				throw new IllegalArgumentException(
					"Row length does not match headers length");
			}

			if (_csvReportRows.contains(csvReportRow)) {
				return;
			}

			_csvReportRows.add(csvReportRow);
		}

		@Override
		public String toString() {
			StringBuilder sb = null;

			for (Row csvReportRow : _csvReportRows) {
				if (sb == null) {
					sb = new StringBuilder();
				}
				else {
					sb.append("\n");
				}

				sb.append(csvReportRow.toString());
			}

			return sb.toString();
		}

		protected static final class Row extends ArrayList {

			public Row() {
			}

			public Row(String... strings) {
				for (String string : strings) {
					add(string);
				}
			}

			@Override
			public boolean equals(Object object) {
				if (this == object) {
					return true;
				}

				if (!(object instanceof Row) ||
					!Objects.equals(toString(), object.toString())) {

					return false;
				}

				return true;
			}

			@Override
			public int hashCode() {
				String string = toString();

				return string.hashCode();
			}

			@Override
			public String toString() {
				return StringUtils.join(iterator(), ",");
			}

		}

		private List _csvReportRows = new ArrayList<>();

	}

	protected static class TestClassDurationComparator
		implements Comparator {

		@Override
		public int compare(TestClass testClass1, TestClass testClass2) {
			Long duration1 =
				testClass1.getAverageDuration() +
					testClass1.getAverageOverheadDuration();
			Long duration2 =
				testClass2.getAverageDuration() +
					testClass2.getAverageOverheadDuration();

			return duration2.compareTo(duration1);
		}

	}

	private long _getDefaultTestDuration() {
		JobProperty jobProperty = getJobProperty(
			"test.batch.default.test.duration");

		if (jobProperty == null) {
			return 0L;
		}

		String jobPropertyValue = jobProperty.getValue();

		if (JenkinsResultsParserUtil.isNullOrEmpty(jobPropertyValue)) {
			return 0L;
		}

		recordJobProperty(jobProperty);

		return Long.valueOf(jobPropertyValue);
	}

	private long _getDefaultTestOverheadDuration() {
		JobProperty jobProperty = getJobProperty(
			"test.batch.default.test.overhead.duration");

		if (jobProperty == null) {
			return 0L;
		}

		String jobPropertyValue = jobProperty.getValue();

		if (JenkinsResultsParserUtil.isNullOrEmpty(jobPropertyValue)) {
			return 0L;
		}

		recordJobProperty(jobProperty);

		return Long.valueOf(jobPropertyValue);
	}

	private long _getDefaultTestTaskDuration() {
		JobProperty jobProperty = getJobProperty(
			"test.batch.default.test.task.duration");

		if (jobProperty == null) {
			return 0L;
		}

		String jobPropertyValue = jobProperty.getValue();

		if (JenkinsResultsParserUtil.isNullOrEmpty(jobPropertyValue)) {
			return 0L;
		}

		recordJobProperty(jobProperty);

		return Long.valueOf(jobPropertyValue);
	}

	private Map _getJobPropertiesMap() {
		Map batchProperties = new TreeMap<>();

		for (JobProperty jobProperty : _jobProperties) {
			String jobPropertyValue = jobProperty.getValue();

			if (jobPropertyValue == null) {
				continue;
			}

			String propertiesFilePath = jobProperty.getPropertiesFilePath();

			Properties properties = batchProperties.get(propertiesFilePath);

			if (properties == null) {
				properties = new Properties();
			}

			properties.setProperty(jobProperty.getName(), jobPropertyValue);

			batchProperties.put(propertiesFilePath, properties);
		}

		return batchProperties;
	}

	private JobProperty _getJobProperty(
		String basePropertyName, String testSuiteName, String testBatchName,
		File testBaseDir, JobProperty.Type type, boolean useBasePropertyName) {

		if (testBatchName == null) {
			testBatchName = getBatchName();
		}

		return JobPropertyFactory.newJobProperty(
			basePropertyName, testSuiteName, testBatchName, getJob(),
			testBaseDir, type, useBasePropertyName);
	}

	private JobProperty _getJobProperty(
		String basePropertyName, String testSuiteName, String testBatchName,
		String ruleName, File testBaseDir, JobProperty.Type type,
		boolean useBasePropertyName) {

		if (testBatchName == null) {
			testBatchName = getBatchName();
		}

		return JobPropertyFactory.newJobProperty(
			basePropertyName, testSuiteName, testBatchName, ruleName, getJob(),
			testBaseDir, type, useBasePropertyName);
	}

	private List _getRequiredModuleDirs(
		List moduleDirs, List requiredModuleDirs) {

		List modifiedPoshiModulesList = new ArrayList<>();
		List modifiedNonposhiModulesList = new ArrayList<>();

		try {
			modifiedPoshiModulesList =
				portalGitWorkingDirectory.getModifiedPoshiModules();
			modifiedNonposhiModulesList =
				portalGitWorkingDirectory.getModifiedNonposhiModules();
		}
		catch (IOException ioException) {
			File workingDirectory =
				portalGitWorkingDirectory.getWorkingDirectory();

			throw new RuntimeException(
				JenkinsResultsParserUtil.combine(
					"Unable to get modified modules with non poshi and poshi " +
						"changes directories in ",
					workingDirectory.getPath()),
				ioException);
		}

		File modulesBaseDir = new File(
			portalGitWorkingDirectory.getWorkingDirectory(), "modules");

		for (File moduleDir : moduleDirs) {
			if (testRelevantChanges &&
				modifiedPoshiModulesList.contains(moduleDir) &&
				!modifiedNonposhiModulesList.contains(moduleDir)) {

				continue;
			}

			JobProperty jobProperty = getJobProperty(
				"modules.includes.required[" + getTestSuiteName() + "]",
				moduleDir, JobProperty.Type.MODULE_TEST_DIR);

			String jobPropertyValue = jobProperty.getValue();

			if (jobPropertyValue == null) {
				continue;
			}

			recordJobProperty(jobProperty);

			for (String requiredModuleDirPath : jobPropertyValue.split(",")) {
				File requiredModuleDir = new File(
					modulesBaseDir, requiredModuleDirPath);

				if (!requiredModuleDir.exists() ||
					requiredModuleDirs.contains(requiredModuleDir)) {

					continue;
				}

				requiredModuleDirs.add(requiredModuleDir);
			}
		}

		return new ArrayList<>(requiredModuleDirs);
	}

	private TestTaskHistory _getTestTaskHistory(String testName) {
		if (_testTaskHistories.containsKey(testName)) {
			return _testTaskHistories.get(testName);
		}

		BatchHistory batchHistory = getBatchHistory();

		if (batchHistory == null) {
			return null;
		}

		TestHistory testHistory = batchHistory.getTestHistory(testName);

		if (testHistory == null) {
			return null;
		}

		_testTaskHistories.put(testName, testHistory.getTestTaskHistory());

		return _testTaskHistories.get(testName);
	}

	private List> _partitionByMaxChildren(
		List> axisTestClassGroupsList) {

		List> partitionedAxisTestClassGroupsList =
			new ArrayList<>();

		for (List axisTestClassGroups :
				axisTestClassGroupsList) {

			partitionedAxisTestClassGroupsList.addAll(
				Lists.partition(axisTestClassGroups, getSegmentMaxChildren()));
		}

		return partitionedAxisTestClassGroupsList;
	}

	private List> _partitionByMinimumSlaveRAM(
		List> axisTestClassGroupsList) {

		List> partitionedAxisTestClassGroupsList =
			new ArrayList<>();

		for (List axisTestClassGroups :
				axisTestClassGroupsList) {

			Map> axisTestClassGroupsMap =
				new HashMap<>();

			for (AxisTestClassGroup axisTestClassGroup : axisTestClassGroups) {
				Integer minimumSlaveRAM =
					axisTestClassGroup.getMinimumSlaveRAM();

				List minimumSlaveRAMAxisTestClassGroups =
					axisTestClassGroupsMap.get(minimumSlaveRAM);

				if (minimumSlaveRAMAxisTestClassGroups == null) {
					minimumSlaveRAMAxisTestClassGroups = new ArrayList<>();
				}

				minimumSlaveRAMAxisTestClassGroups.add(axisTestClassGroup);

				axisTestClassGroupsMap.put(
					minimumSlaveRAM, minimumSlaveRAMAxisTestClassGroups);
			}

			partitionedAxisTestClassGroupsList.addAll(
				axisTestClassGroupsMap.values());
		}

		return partitionedAxisTestClassGroupsList;
	}

	private List> _partitionBySlaveLabel(
		List> axisTestClassGroupsList) {

		List> partitionedAxisTestClassGroupsList =
			new ArrayList<>();

		for (List axisTestClassGroups :
				axisTestClassGroupsList) {

			Map> axisTestClassGroupsMap =
				new HashMap<>();

			for (AxisTestClassGroup axisTestClassGroup : axisTestClassGroups) {
				String slaveLabel = axisTestClassGroup.getSlaveLabel();

				List slaveLabelAxisTestClassGroups =
					axisTestClassGroupsMap.get(slaveLabel);

				if (slaveLabelAxisTestClassGroups == null) {
					slaveLabelAxisTestClassGroups = new ArrayList<>();
				}

				slaveLabelAxisTestClassGroups.add(axisTestClassGroup);

				axisTestClassGroupsMap.put(
					slaveLabel, slaveLabelAxisTestClassGroups);
			}

			partitionedAxisTestClassGroupsList.addAll(
				axisTestClassGroupsMap.values());
		}

		return partitionedAxisTestClassGroupsList;
	}

	private List> _partitionByTestBaseDir(
		List> axisTestClassGroupsList) {

		List> partitionedAxisTestClassGroupsList =
			new ArrayList<>();

		for (List axisTestClassGroups :
				axisTestClassGroupsList) {

			Map> axisTestClassGroupsMap =
				new HashMap<>();

			for (AxisTestClassGroup axisTestClassGroup : axisTestClassGroups) {
				File testBaseDir = axisTestClassGroup.getTestBaseDir();

				List testBaseDirAxisTestClassGroups =
					axisTestClassGroupsMap.get(testBaseDir);

				if (testBaseDirAxisTestClassGroups == null) {
					testBaseDirAxisTestClassGroups = new ArrayList<>();
				}

				testBaseDirAxisTestClassGroups.add(axisTestClassGroup);

				axisTestClassGroupsMap.put(
					testBaseDir, testBaseDirAxisTestClassGroups);
			}

			partitionedAxisTestClassGroupsList.addAll(
				axisTestClassGroupsMap.values());
		}

		return partitionedAxisTestClassGroupsList;
	}

	private void _setIncludeStableTestSuite() {
		includeStableTestSuite = testRelevantChanges;
	}

	private void _setTestHotfixChanges() {
		Job job = getJob();

		testHotfixChanges = job.testHotfixChanges();
	}

	private void _setTestReleaseBundle() {
		Job job = getJob();

		testReleaseBundle = job.testReleaseBundle();
	}

	private void _setTestRelevantChanges() {
		Job job = getJob();

		testRelevantChanges = job.testRelevantChanges();
	}

	private void _setTestRelevantChangesInStable() {
		Job job = getJob();

		testRelevantChangesInStable = job.testRelevantChangesInStable();
	}

	private void _setTestRelevantJUnitTestsOnly() {
		Job job = getJob();

		if (testRelevantChanges && job.isJUnitTestsModifiedOnly()) {
			testRelevantJUnitTestsOnly = true;

			return;
		}

		testRelevantJUnitTestsOnly = false;
	}

	private void _setTestRelevantJUnitTestsOnlyInStable() {
		Job job = getJob();

		if (testRelevantChangesInStable && job.isJUnitTestsModifiedOnly()) {
			testRelevantJUnitTestsOnlyInStable = true;

			return;
		}

		testRelevantJUnitTestsOnlyInStable = false;
	}

	private static final int _SEGMENT_MAX_CHILDREN_DEFAULT = 25;

	private static final Pattern _jobNamePattern = Pattern.compile(
		"(?.*)(?\\([^\\)]+\\))");

	private final Map _averageTestDurations = new HashMap<>();
	private final Map _averageTestOverheadDurations =
		new HashMap<>();
	private BatchHistory _batchHistory;
	private final List _jobProperties = new ArrayList<>();
	private final List _segmentTestClassGroups =
		new ArrayList<>();
	private Boolean _testAnalyticsCloud;
	private final Map _testTaskHistories =
		new HashMap<>();

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy