com.liferay.jenkins.results.parser.test.clazz.group.FunctionalBatchTestClassGroup Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of com.liferay.jenkins.results.parser
Show all versions of com.liferay.jenkins.results.parser
Liferay Jenkins Results Parser
/**
* 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.liferay.jenkins.results.parser.AntException;
import com.liferay.jenkins.results.parser.AntUtil;
import com.liferay.jenkins.results.parser.JenkinsResultsParserUtil;
import com.liferay.jenkins.results.parser.PortalGitWorkingDirectory;
import com.liferay.jenkins.results.parser.PortalHotfixReleaseJob;
import com.liferay.jenkins.results.parser.PortalTestClassJob;
import com.liferay.jenkins.results.parser.job.property.JobProperty;
import com.liferay.jenkins.results.parser.test.batch.PoshiTestBatch;
import com.liferay.jenkins.results.parser.test.batch.PoshiTestSelector;
import com.liferay.jenkins.results.parser.test.clazz.TestClass;
import com.liferay.jenkins.results.parser.test.clazz.TestClassBalancedListSplitter;
import com.liferay.jenkins.results.parser.test.clazz.TestClassFactory;
import com.liferay.poshi.core.PoshiContext;
import com.liferay.poshi.core.util.PropsUtil;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.json.JSONObject;
/**
* @author Yi-Chen Tsai
*/
public class FunctionalBatchTestClassGroup extends BatchTestClassGroup {
@Override
public int getAxisCount() {
if (ignore()) {
return 0;
}
return axisTestClassGroups.size();
}
@Override
public JSONObject getJSONObject() {
if (jsonObject != null) {
return jsonObject;
}
jsonObject = super.getJSONObject();
StringBuilder sb = new StringBuilder();
sb.append("(");
sb.append(getTestBatchRunPropertyQuery());
sb.append(") AND (ignored == null)");
String testRunEnvironment = PropsUtil.get("test.run.environment");
if (!JenkinsResultsParserUtil.isNullOrEmpty(testRunEnvironment)) {
sb.append(" AND (test.run.environment == \"");
sb.append(testRunEnvironment);
sb.append("\" OR test.run.environment == null)");
}
jsonObject.put("pql_query", sb.toString());
jsonObject.put("target_duration", getTargetAxisDuration());
jsonObject.put(
"test_batch_run_property_queries", _testBatchRunPropertyQueries);
return jsonObject;
}
public List getTestBaseDirs() {
String testBaseDirPath = _getTestBaseDirPath();
if (!JenkinsResultsParserUtil.isNullOrEmpty(testBaseDirPath)) {
return Arrays.asList(new File(testBaseDirPath));
}
return Arrays.asList(
new File(
portalGitWorkingDirectory.getWorkingDirectory(),
"portal-web/test/functional/portalweb"));
}
public String getTestBatchRunPropertyQuery() {
List testBaseDirs = getTestBaseDirs();
if (testBaseDirs.isEmpty()) {
return null;
}
return getTestBatchRunPropertyQuery(testBaseDirs.get(0));
}
public String getTestBatchRunPropertyQuery(File testBaseDir) {
return _testBatchRunPropertyQueries.get(testBaseDir);
}
@Override
public List getTestClasses() {
List testClasses = new ArrayList<>();
for (AxisTestClassGroup axisTestClassGroup : axisTestClassGroups) {
testClasses.addAll(axisTestClassGroup.getTestClasses());
}
return testClasses;
}
public String getWorkspaceName() {
JobProperty jobProperty = getJobProperty(
"test.workspace.name", testSuiteName, batchName);
if ((jobProperty == null) ||
JenkinsResultsParserUtil.isNullOrEmpty(jobProperty.getValue())) {
return null;
}
recordJobProperty(jobProperty);
return jobProperty.getValue();
}
public boolean isUpgradeFile(File file) {
Matcher matcher = _upgradeFileNamePattern.matcher(file.toString());
if (matcher.find()) {
return true;
}
return false;
}
protected FunctionalBatchTestClassGroup(
JSONObject jsonObject, PortalTestClassJob portalTestClassJob) {
super(jsonObject, portalTestClassJob);
JSONObject testBatchRunPropertyQueriesJSONObject =
jsonObject.optJSONObject("test_batch_run_property_queries");
if (testBatchRunPropertyQueriesJSONObject == null) {
return;
}
for (String key : testBatchRunPropertyQueriesJSONObject.keySet()) {
_testBatchRunPropertyQueries.put(
new File(key),
testBatchRunPropertyQueriesJSONObject.getString(key));
}
}
protected FunctionalBatchTestClassGroup(
String batchName, PortalTestClassJob portalTestClassJob) {
super(batchName, portalTestClassJob);
if (ignore()) {
return;
}
_setTestBatchRunPropertyQueries();
setAxisTestClassGroups();
setSegmentTestClassGroups();
}
protected FunctionalBatchTestClassGroup(
String batchName, PortalTestClassJob portalTestClassJob,
PoshiTestBatch poshiTestBatch) {
super(batchName, portalTestClassJob);
if (ignore()) {
return;
}
_setTestBatchRunPropertyQueries(poshiTestBatch.getTestSelector());
setAxisTestClassGroups();
setSegmentTestClassGroups();
}
@Override
protected int getAxisMaxSize() {
long targetAxisDuration = getTargetAxisDuration();
if (targetAxisDuration > 0) {
return AXES_SIZE_MAX_DEFAULT;
}
return super.getAxisMaxSize();
}
protected String getDefaultTestBatchRunPropertyQuery(
File testBaseDir, String testSuiteName) {
String query = System.getenv("TEST_BATCH_RUN_PROPERTY_QUERY");
if (JenkinsResultsParserUtil.isNullOrEmpty(query)) {
query = getBuildStartProperty("TEST_BATCH_RUN_PROPERTY_QUERY");
}
if (!JenkinsResultsParserUtil.isNullOrEmpty(query)) {
return query;
}
JobProperty jobProperty = getJobProperty(
"test.batch.run.property.query", testSuiteName, batchName);
File testPropertiesFile = new File(
portalGitWorkingDirectory.getWorkingDirectory(), "test.properties");
JenkinsResultsParserUtil.validatePQL(
jobProperty.getValue(), testPropertiesFile);
recordJobProperty(jobProperty);
return jobProperty.getValue();
}
protected List getModifiedFiles() {
synchronized (_poshiTestCasePattern) {
if (_modifiedFiles != null) {
return _modifiedFiles;
}
_modifiedFiles = new ArrayList<>();
if (portalTestClassJob instanceof PortalHotfixReleaseJob) {
PortalHotfixReleaseJob portalHotfixReleaseJob =
(PortalHotfixReleaseJob)portalTestClassJob;
_modifiedFiles = portalHotfixReleaseJob.getModifiedFiles();
}
else {
_modifiedFiles =
portalGitWorkingDirectory.getModifiedFilesList();
}
return _modifiedFiles;
}
}
protected List> getPoshiTestClassGroups(File testBaseDir) {
String query = getTestBatchRunPropertyQuery(testBaseDir);
if (JenkinsResultsParserUtil.isNullOrEmpty(query)) {
return new ArrayList<>();
}
synchronized (_poshiTestCasePattern) {
File cachedTestBaseDir = _testBaseDirAtomicReference.get();
if ((cachedTestBaseDir == null) ||
!cachedTestBaseDir.equals(testBaseDir)) {
PortalGitWorkingDirectory portalGitWorkingDirectory =
portalTestClassJob.getPortalGitWorkingDirectory();
File portalWorkingDirectory =
portalGitWorkingDirectory.getWorkingDirectory();
Map parameters = new HashMap<>();
String testBaseDirPath = null;
if ((testBaseDir != null) && testBaseDir.exists()) {
testBaseDirPath = JenkinsResultsParserUtil.getCanonicalPath(
testBaseDir);
parameters.put("test.base.dir.name", testBaseDirPath);
}
try {
AntUtil.callTarget(
portalWorkingDirectory, "build-test.xml",
"prepare-poshi-runner-properties", parameters);
}
catch (AntException antException) {
throw new RuntimeException(antException);
}
Properties properties = JenkinsResultsParserUtil.getProperties(
new File(
portalWorkingDirectory, "portal-web/poshi.properties"),
new File(
portalWorkingDirectory,
"portal-web/poshi-ext.properties"));
File poshiPropertiesFile = new File(
testBaseDirPath, "poshi.properties");
if (poshiPropertiesFile.exists()) {
properties = JenkinsResultsParserUtil.getProperties(
poshiPropertiesFile,
new File(testBaseDirPath, "poshi-ext.properties"));
}
if (!JenkinsResultsParserUtil.isNullOrEmpty(testBaseDirPath)) {
properties.setProperty(
"test.base.dir.name", testBaseDirPath);
}
properties.setProperty("poshi.file.read.thread.pool", "4");
properties.setProperty("poshi.file.read.timeout", "30");
PropsUtil.clear();
PropsUtil.setProperties(properties);
try {
PoshiContext.clear();
PoshiContext.readFiles();
}
catch (Exception exception) {
throw new RuntimeException(exception);
}
_testBaseDirAtomicReference.set(testBaseDir);
}
try {
return getTestClassGroups(
PoshiContext.getTestBatchGroups(query, getAxisMaxSize()));
}
catch (Exception exception) {
throw new RuntimeException(exception);
}
}
}
protected List> getTestClassGroups(
List> testBatchGroups) {
List> testClassGroups = new ArrayList<>();
if (testBatchGroups.isEmpty()) {
return testClassGroups;
}
for (List testBatchGroup : testBatchGroups) {
List testClassGroup = new ArrayList<>();
for (String testClassMethodName : testBatchGroup) {
testClassGroup.add(
TestClassFactory.newTestClass(this, testClassMethodName));
}
testClassGroups.add(testClassGroup);
}
return testClassGroups;
}
@Override
protected void setAxisTestClassGroups() {
if (!axisTestClassGroups.isEmpty()) {
return;
}
for (File testBaseDir : getTestBaseDirs()) {
String query = getTestBatchRunPropertyQuery(testBaseDir);
if (query == null) {
continue;
}
List> poshiTestClassGroups =
getPoshiTestClassGroups(testBaseDir);
long targetAxisDuration = getTargetAxisDuration();
for (List poshiTestClassGroup : poshiTestClassGroups) {
if (poshiTestClassGroup.isEmpty()) {
continue;
}
if (targetAxisDuration > 0) {
TestClassBalancedListSplitter
testClassBalancedListSplitter =
new TestClassBalancedListSplitter(
targetAxisDuration);
List> testClassLists =
testClassBalancedListSplitter.split(
poshiTestClassGroup);
for (List testClassList : testClassLists) {
AxisTestClassGroup axisTestClassGroup =
TestClassGroupFactory.newAxisTestClassGroup(
this, testBaseDir);
axisTestClassGroup.addTestClasses(testClassList);
axisTestClassGroups.add(axisTestClassGroup);
}
}
else {
AxisTestClassGroup axisTestClassGroup =
TestClassGroupFactory.newAxisTestClassGroup(
this, testBaseDir);
for (TestClass testClass : poshiTestClassGroup) {
axisTestClassGroup.addTestClass(testClass);
}
axisTestClassGroups.add(axisTestClassGroup);
}
}
}
}
private String _concatPQL(
File file, String testSuiteName, String concatedPQL) {
if (file == null) {
return null;
}
if (JenkinsResultsParserUtil.isPoshiFile(file)) {
return "";
}
File canonicalFile = JenkinsResultsParserUtil.getCanonicalFile(file);
if (canonicalFile.equals(
portalGitWorkingDirectory.getWorkingDirectory())) {
return concatedPQL;
}
File parentFile = canonicalFile.getParentFile();
if ((parentFile == null) || !parentFile.exists()) {
return "";
}
File modulesBaseDir = new File(
portalGitWorkingDirectory.getWorkingDirectory(), "modules");
Path modulesBaseDirPath = modulesBaseDir.toPath();
Path parentFilePath = parentFile.toPath();
File testPropertiesFile = new File(canonicalFile, "test.properties");
if (modulesBaseDirPath.equals(parentFilePath) &&
!testPropertiesFile.exists()) {
return concatedPQL;
}
if (!canonicalFile.isDirectory() || !testPropertiesFile.exists()) {
return _concatPQL(parentFile, testSuiteName, concatedPQL);
}
if ((_traversedPropertyFiles.contains(testPropertiesFile) &&
testSuiteName.equals("relevant")) ||
_traversedUpgradeFiles.contains(testPropertiesFile)) {
return concatedPQL;
}
if (testSuiteName.equals("upgrades-relevant") &&
!_traversedUpgradeFiles.contains(testPropertiesFile)) {
_traversedUpgradeFiles.add(testPropertiesFile);
}
_traversedPropertyFiles.add(testPropertiesFile);
JobProperty jobProperty = getJobProperty(
"test.batch.run.property.query", testSuiteName, batchName,
canonicalFile, JobProperty.Type.MODULE_TEST_DIR);
String testBatchPropertyQuery = jobProperty.getValue();
if (!JenkinsResultsParserUtil.isNullOrEmpty(testBatchPropertyQuery) &&
!testBatchPropertyQuery.equals("false") &&
!concatedPQL.contains(testBatchPropertyQuery)) {
JenkinsResultsParserUtil.validatePQL(
testBatchPropertyQuery, testPropertiesFile);
recordJobProperty(jobProperty);
if (!concatedPQL.isEmpty()) {
concatedPQL += JenkinsResultsParserUtil.combine(
" OR (", testBatchPropertyQuery, ")");
}
else {
concatedPQL += testBatchPropertyQuery;
}
}
Properties testProperties = JenkinsResultsParserUtil.getProperties(
testPropertiesFile);
boolean ignoreParents = Boolean.valueOf(
JenkinsResultsParserUtil.getProperty(
testProperties, "ignoreParents", false, testSuiteName));
if (ignoreParents ||
parentFile.equals(
portalGitWorkingDirectory.getWorkingDirectory())) {
return concatedPQL;
}
if (!parentFilePath.equals(modulesBaseDirPath)) {
return _concatPQL(parentFile, testSuiteName, concatedPQL);
}
return concatedPQL;
}
private String _getTestBaseDirPath() {
JobProperty jobProperty = getJobProperty(
"test.base.dir", testSuiteName, batchName);
if ((jobProperty == null) ||
JenkinsResultsParserUtil.isNullOrEmpty(jobProperty.getValue())) {
String workspaceName = getWorkspaceName();
if (JenkinsResultsParserUtil.isNullOrEmpty(workspaceName)) {
return null;
}
File testBaseDir = new File(
portalGitWorkingDirectory.getWorkingDirectory(),
JenkinsResultsParserUtil.combine(
"workspaces/", workspaceName, "/poshi"));
if (!testBaseDir.exists()) {
return null;
}
return JenkinsResultsParserUtil.getCanonicalPath(testBaseDir);
}
File testBaseDir = new File(
portalGitWorkingDirectory.getWorkingDirectory(),
jobProperty.getValue());
if (!testBaseDir.exists()) {
return null;
}
recordJobProperty(jobProperty);
return JenkinsResultsParserUtil.getCanonicalPath(testBaseDir);
}
private String _getTestBatchRunPropertyQuery(File testBaseDir) {
if (!testRelevantChanges && !testHotfixChanges) {
String defaultPQL = getDefaultTestBatchRunPropertyQuery(
testBaseDir, testSuiteName);
JobProperty globalJobProperty = getJobProperty(
"test.batch.run.property.global.query", testSuiteName,
batchName);
String globalJobPropertyValue = globalJobProperty.getValue();
if (!JenkinsResultsParserUtil.isNullOrEmpty(
globalJobPropertyValue)) {
JenkinsResultsParserUtil.validatePQL(
globalJobPropertyValue, testBaseDir);
recordJobProperty(globalJobProperty);
return JenkinsResultsParserUtil.combine(
"(", globalJobPropertyValue, ") AND (", defaultPQL, ")");
}
return defaultPQL;
}
File testPropertiesFile = new File(
portalGitWorkingDirectory.getWorkingDirectory(), "test.properties");
StringBuilder sb = new StringBuilder();
for (File modifiedFile : getModifiedFiles()) {
String testBatchPQL = _concatPQL(
modifiedFile, getTestSuiteName(), "");
if (JenkinsResultsParserUtil.isNullOrEmpty(testBatchPQL) ||
testBatchPQL.equals("false")) {
continue;
}
if (sb.indexOf(testBatchPQL) == -1) {
if (!JenkinsResultsParserUtil.isNullOrEmpty(sb.toString())) {
sb.append(" OR ");
}
sb.append("(");
sb.append(testBatchPQL);
sb.append(")");
}
if (isUpgradeFile(modifiedFile)) {
String upgradePQL = _concatPQL(
modifiedFile, "upgrades-relevant", "");
if (!JenkinsResultsParserUtil.isNullOrEmpty(upgradePQL)) {
if (sb.length() > 0) {
sb.append(" OR ");
}
sb.append("(");
sb.append(upgradePQL);
sb.append(")");
}
}
}
String defaultPQL = getDefaultTestBatchRunPropertyQuery(
testBaseDir, testSuiteName);
if (!JenkinsResultsParserUtil.isNullOrEmpty(defaultPQL) &&
(sb.indexOf(defaultPQL) == -1)) {
JenkinsResultsParserUtil.validatePQL(defaultPQL, testBaseDir);
if (sb.length() > 0) {
sb.append(" OR ");
}
sb.append("(");
sb.append(defaultPQL);
sb.append(")");
}
if (!NAME_STABLE_TEST_SUITE.equals(getTestSuiteName())) {
String batchName = getBatchName();
if (!batchName.endsWith("_stable")) {
batchName += "_stable";
}
JobProperty jobProperty = getJobProperty(
"test.batch.run.property.query", NAME_STABLE_TEST_SUITE,
batchName);
String jobPropertyValue = jobProperty.getValue();
if ((jobPropertyValue != null) && includeStableTestSuite &&
isStableTestSuiteBatch(batchName) &&
(sb.indexOf(jobPropertyValue) == -1)) {
JenkinsResultsParserUtil.validatePQL(
jobPropertyValue, testPropertiesFile);
recordJobProperty(jobProperty);
if (sb.length() > 0) {
sb.append(" OR ");
}
sb.append("(");
sb.append(jobPropertyValue);
sb.append(")");
}
}
String testBatchRunPropertyQuery = sb.toString();
JobProperty jobProperty = getJobProperty(
"test.batch.run.property.global.query", testSuiteName, batchName);
String jobPropertyValue = jobProperty.getValue();
if (jobPropertyValue != null) {
JenkinsResultsParserUtil.validatePQL(
jobPropertyValue, testPropertiesFile);
recordJobProperty(jobProperty);
testBatchRunPropertyQuery = JenkinsResultsParserUtil.combine(
"(", jobPropertyValue, ") AND (", testBatchRunPropertyQuery,
")");
}
return testBatchRunPropertyQuery;
}
private void _setTestBatchRunPropertyQueries() {
if (isRootCauseAnalysis()) {
String portalBatchTestSelector = System.getenv(
"PORTAL_BATCH_TEST_SELECTOR");
if (JenkinsResultsParserUtil.isNullOrEmpty(
portalBatchTestSelector)) {
portalBatchTestSelector = getBuildStartProperty(
"PORTAL_BATCH_TEST_SELECTOR");
}
if ((portalBatchTestSelector != null) &&
portalBatchTestSelector.startsWith("LocalFile.")) {
portalBatchTestSelector = portalBatchTestSelector.replace(
"LocalFile.", "");
}
_testBatchRunPropertyQueries.put(
new File(
portalGitWorkingDirectory.getWorkingDirectory(),
"portal-web/test/functional/portalweb"),
"test.class.method.name == " + portalBatchTestSelector);
return;
}
for (File testBaseDir : getTestBaseDirs()) {
String testBatchRunPropertyQuery = _getTestBatchRunPropertyQuery(
testBaseDir);
if (JenkinsResultsParserUtil.isNullOrEmpty(
testBatchRunPropertyQuery)) {
continue;
}
_testBatchRunPropertyQueries.put(
testBaseDir, testBatchRunPropertyQuery);
}
}
private void _setTestBatchRunPropertyQueries(
PoshiTestSelector poshiTestSelector) {
recordJobProperties(poshiTestSelector.getPoshiJobProperties());
PortalGitWorkingDirectory portalGitWorkingDirectory =
portalTestClassJob.getPortalGitWorkingDirectory();
_testBatchRunPropertyQueries.put(
new File(
portalGitWorkingDirectory.getWorkingDirectory(),
"portal-web/test/functional/portalweb"),
poshiTestSelector.getPoshiQuery());
}
private static List _modifiedFiles;
private static final Pattern _poshiTestCasePattern = Pattern.compile(
"(?[^\\.]+)\\.(?[^\\#]+)\\#(?.*)");
private static final AtomicReference _testBaseDirAtomicReference =
new AtomicReference<>();
private static final Pattern _upgradeFileNamePattern = Pattern.compile(
"(.*\\/verify\\/.*|.*\\/upgrade\\/.*|.*\\.sql)");
private final Map _testBatchRunPropertyQueries =
new HashMap<>();
private final Set _traversedPropertyFiles = new HashSet<>();
private final Set _traversedUpgradeFiles = new HashSet<>();
}