Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.qameta.allure.util.ResultsUtils Maven / Gradle / Ivy
/*
* Copyright 2016-2024 Qameta Software Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.qameta.allure.util;
import io.qameta.allure.Description;
import io.qameta.allure.Epic;
import io.qameta.allure.Feature;
import io.qameta.allure.Owner;
import io.qameta.allure.Severity;
import io.qameta.allure.SeverityLevel;
import io.qameta.allure.Story;
import io.qameta.allure.model.Label;
import io.qameta.allure.model.Link;
import io.qameta.allure.model.Parameter;
import io.qameta.allure.model.Status;
import io.qameta.allure.model.StatusDetails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static io.qameta.allure.util.PropertiesUtils.loadAllureProperties;
import static java.lang.Boolean.parseBoolean;
import static java.util.Objects.nonNull;
/**
* The collection of Allure utils methods.
*/
@SuppressWarnings({
"ClassFanOutComplexity",
"ClassDataAbstractionCoupling",
"PMD.ExcessiveImports",
"PMD.TooManyMethods",
})
public final class ResultsUtils {
public static final String ALLURE_HOST_NAME_SYSPROP = "allure.hostName";
public static final String ALLURE_HOST_NAME_ENV = "ALLURE_HOST_NAME";
public static final String ALLURE_THREAD_NAME_SYSPROP = "allure.threadName";
public static final String ALLURE_THREAD_NAME_ENV = "ALLURE_THREAD_NAME";
public static final String ALLURE_SEPARATE_LINES_SYSPROP = "allure.description.javadoc.separateLines";
public static final String ISSUE_LINK_TYPE = "issue";
public static final String TMS_LINK_TYPE = "tms";
public static final String CUSTOM_LINK_TYPE = "custom";
public static final String ALLURE_ID_LABEL_NAME = "AS_ID";
public static final String SUITE_LABEL_NAME = "suite";
public static final String PARENT_SUITE_LABEL_NAME = "parentSuite";
public static final String SUB_SUITE_LABEL_NAME = "subSuite";
public static final String EPIC_LABEL_NAME = "epic";
public static final String FEATURE_LABEL_NAME = "feature";
public static final String STORY_LABEL_NAME = "story";
public static final String SEVERITY_LABEL_NAME = "severity";
public static final String TAG_LABEL_NAME = "tag";
public static final String OWNER_LABEL_NAME = "owner";
public static final String LEAD_LABEL_NAME = "lead";
public static final String HOST_LABEL_NAME = "host";
public static final String THREAD_LABEL_NAME = "thread";
public static final String TEST_METHOD_LABEL_NAME = "testMethod";
public static final String TEST_CLASS_LABEL_NAME = "testClass";
public static final String PACKAGE_LABEL_NAME = "package";
public static final String FRAMEWORK_LABEL_NAME = "framework";
public static final String LANGUAGE_LABEL_NAME = "language";
private static final Logger LOGGER = LoggerFactory.getLogger(ResultsUtils.class);
private static final String ALLURE_DESCRIPTIONS_FOLDER = "META-INF/allureDescriptions/";
private static final String MD_5 = "MD5";
private static String cachedHost;
private ResultsUtils() {
throw new IllegalStateException("Do not instance");
}
public static Parameter createParameter(final String name, final Object value) {
return createParameter(name, value, null, null);
}
public static Parameter createParameter(final String name, final Object value,
final Boolean excluded, final Parameter.Mode mode) {
return new Parameter()
.setName(name)
.setValue(ObjectUtils.toString(value))
.setExcluded(excluded)
.setMode(mode);
}
public static Label createSuiteLabel(final String suite) {
return createLabel(SUITE_LABEL_NAME, suite);
}
public static Label createParentSuiteLabel(final String suite) {
return createLabel(PARENT_SUITE_LABEL_NAME, suite);
}
public static Label createSubSuiteLabel(final String suite) {
return createLabel(SUB_SUITE_LABEL_NAME, suite);
}
public static Label createTestMethodLabel(final String testMethod) {
return createLabel(TEST_METHOD_LABEL_NAME, testMethod);
}
public static Label createTestClassLabel(final String testClass) {
return createLabel(TEST_CLASS_LABEL_NAME, testClass);
}
public static Label createPackageLabel(final String packageName) {
return createLabel(PACKAGE_LABEL_NAME, packageName);
}
public static Label createEpicLabel(final String epic) {
return createLabel(EPIC_LABEL_NAME, epic);
}
public static Label createFeatureLabel(final String feature) {
return createLabel(FEATURE_LABEL_NAME, feature);
}
public static Label createStoryLabel(final String story) {
return createLabel(STORY_LABEL_NAME, story);
}
public static Label createTagLabel(final String tag) {
return createLabel(TAG_LABEL_NAME, tag);
}
public static Label createOwnerLabel(final String owner) {
return createLabel(OWNER_LABEL_NAME, owner);
}
public static Label createSeverityLabel(final SeverityLevel severity) {
return createSeverityLabel(severity.value());
}
public static Label createSeverityLabel(final String severity) {
return createLabel(SEVERITY_LABEL_NAME, severity);
}
public static Label createHostLabel() {
return createLabel(HOST_LABEL_NAME, getHostName());
}
public static Label createThreadLabel() {
return createLabel(THREAD_LABEL_NAME, getThreadName());
}
public static Label createFrameworkLabel(final String framework) {
return createLabel(FRAMEWORK_LABEL_NAME, framework);
}
public static Label createLanguageLabel(final String language) {
return createLabel(LANGUAGE_LABEL_NAME, language);
}
public static Label createLabel(final String name, final String value) {
return new Label().setName(name).setValue(value);
}
public static Label createLabel(final Owner owner) {
return createOwnerLabel(owner.value());
}
public static Label createLabel(final Severity severity) {
return createSeverityLabel(severity.value());
}
public static Label createLabel(final Story story) {
return createStoryLabel(story.value());
}
public static Label createLabel(final Feature feature) {
return createFeatureLabel(feature.value());
}
public static Label createLabel(final Epic epic) {
return createEpicLabel(epic.value());
}
public static Link createIssueLink(final String value) {
return createLink(value, null, null, ISSUE_LINK_TYPE);
}
public static Link createTmsLink(final String value) {
return createLink(value, null, null, TMS_LINK_TYPE);
}
public static Link createLink(final io.qameta.allure.Link link) {
return createLink(link.value(), link.name(), link.url(), link.type());
}
public static Link createLink(final io.qameta.allure.Issue link) {
return createIssueLink(link.value());
}
public static Link createLink(final io.qameta.allure.TmsLink link) {
return createTmsLink(link.value());
}
@SuppressWarnings("PMD.UseObjectForClearerAPI")
public static Link createLink(final String value, final String name,
final String url, final String type) {
final String resolvedName = firstNonEmpty(value).orElse(name);
final String resolvedUrl = firstNonEmpty(url)
.orElseGet(() -> getLinkUrl(resolvedName, type));
return new Link()
.setName(resolvedName)
.setUrl(resolvedUrl)
.setType(type);
}
public static Set getProvidedLabels() {
final Properties properties = loadAllureProperties();
final Set propertyNames = properties.stringPropertyNames();
return propertyNames.stream()
.filter(name -> name.startsWith("allure.label."))
.map(name -> {
final String labelName = name.substring(13);
final String labelValue = properties.getProperty(name);
return new Label()
.setName(labelName)
.setValue(labelValue);
})
.filter(label -> nonNull(label.getValue()))
.collect(Collectors.toSet());
}
public static String getHostName() {
final String fromProperty = System.getProperty(ALLURE_HOST_NAME_SYSPROP);
final String fromEnv = System.getenv(ALLURE_HOST_NAME_ENV);
return Stream.of(fromProperty, fromEnv)
.filter(Objects::nonNull)
.findFirst()
.orElseGet(ResultsUtils::getRealHostName);
}
public static String getThreadName() {
final String fromProperty = System.getProperty(ALLURE_THREAD_NAME_SYSPROP);
final String fromEnv = System.getenv(ALLURE_THREAD_NAME_ENV);
return Stream.of(fromProperty, fromEnv)
.filter(Objects::nonNull)
.findFirst()
.orElseGet(ResultsUtils::getRealThreadName);
}
public static Optional getStatus(final Throwable throwable) {
return Optional.ofNullable(throwable)
.map(t -> t instanceof AssertionError ? Status.FAILED : Status.BROKEN);
}
public static Optional getStatusDetails(final Throwable e) {
return Optional.ofNullable(e)
.map(throwable -> new StatusDetails()
.setMessage(Optional
.ofNullable(throwable.getMessage())
.orElse(throwable.getClass().getName())
)
.setTrace(getStackTraceAsString(throwable))
);
}
public static Optional getJavadocDescription(final ClassLoader classLoader,
final Method method) {
final String name = method.getName();
final List parameterTypes = Stream.of(method.getParameterTypes())
.map(Class::getTypeName)
.collect(Collectors.toList());
final String signatureHash = generateMethodSignatureHash(
method.getDeclaringClass().getName(),
name,
parameterTypes);
return readResource(classLoader, ALLURE_DESCRIPTIONS_FOLDER + signatureHash)
.map(desc -> separateLines() ? desc.replace("\n", " ") : desc);
}
public static Optional firstNonEmpty(final String... items) {
return Stream.of(items)
.filter(Objects::nonNull)
.filter(item -> !item.isEmpty())
.findFirst();
}
public static String getLinkTypePatternPropertyName(final String type) {
return String.format("allure.link.%s.pattern", type);
}
public static String generateMethodSignatureHash(final String className,
final String methodName,
final List parameterTypes) {
final MessageDigest md = getMd5Digest();
md.update(className.getBytes(StandardCharsets.UTF_8));
md.update(methodName.getBytes(StandardCharsets.UTF_8));
parameterTypes.stream()
.map(string -> string.getBytes(StandardCharsets.UTF_8))
.forEach(md::update);
final byte[] bytes = md.digest();
return bytesToHex(bytes);
}
public static String md5(final String source) {
Objects.requireNonNull(source, "null source");
return bytesToHex(getMd5Digest().digest(source.getBytes(StandardCharsets.UTF_8)));
}
public static String bytesToHex(final byte[] bytes) {
return new BigInteger(1, bytes).toString(16);
}
public static MessageDigest getMd5Digest() {
try {
return MessageDigest.getInstance(MD_5);
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException("Can not find hashing algorithm", e);
}
}
private static String getLinkUrl(final String name, final String type) {
final Properties properties = loadAllureProperties();
final String pattern = properties.getProperty(getLinkTypePatternPropertyName(type));
if (Objects.isNull(pattern)) {
return null;
}
return pattern.replaceAll("\\{}", Objects.isNull(name) ? "" : name);
}
private static String getRealHostName() {
if (Objects.isNull(cachedHost)) {
try {
cachedHost = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
LOGGER.debug("Could not get host name", e);
cachedHost = "default";
}
}
return cachedHost;
}
private static String getRealThreadName() {
return String.format("%s.%s(%s)",
ManagementFactory.getRuntimeMXBean().getName(),
Thread.currentThread().getName(),
Thread.currentThread().getId());
}
private static String getStackTraceAsString(final Throwable throwable) {
final StringWriter stringWriter = new StringWriter();
throwable.printStackTrace(new PrintWriter(stringWriter));
return stringWriter.toString();
}
public static void processDescription(final ClassLoader classLoader,
final Method method,
final Consumer setDescription,
final Consumer setDescriptionHtml) {
if (method.isAnnotationPresent(Description.class)) {
final Description annotation = method.getAnnotation(Description.class);
if ("".equals(annotation.value())) {
getJavadocDescription(classLoader, method)
.ifPresent(setDescriptionHtml);
} else {
final String description = annotation.value();
setDescription.accept(description);
}
}
}
private static Optional readResource(final ClassLoader classLoader, final String resourceName) {
try (InputStream is = classLoader.getResourceAsStream(resourceName)) {
if (Objects.isNull(is)) {
return Optional.empty();
}
final byte[] bytes = toBytes(is);
return Optional.of(new String(bytes, StandardCharsets.UTF_8));
} catch (IOException e) {
LOGGER.warn("Unable to process description resource file", e);
}
return Optional.empty();
}
private static byte[] toBytes(final InputStream is) throws IOException {
final ByteArrayOutputStream output = new ByteArrayOutputStream();
final byte[] buffer = new byte[4096];
int n;
do {
n = is.read(buffer);
if (n > 0) {
output.write(buffer, 0, n);
}
} while (-1 != n);
return output.toByteArray();
}
private static boolean separateLines() {
return parseBoolean(loadAllureProperties().getProperty(ALLURE_SEPARATE_LINES_SYSPROP));
}
}