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.
org.junit.platform.launcher.listeners.MutableTestExecutionSummary Maven / Gradle / Ivy
/*
* Copyright 2015-2019 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/
package org.junit.platform.launcher.listeners;
import static java.lang.String.join;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import org.junit.platform.launcher.TestIdentifier;
import org.junit.platform.launcher.TestPlan;
/**
* Mutable, internal implementation of the {@link TestExecutionSummary} API.
*
* @since 1.0
*/
class MutableTestExecutionSummary implements TestExecutionSummary {
private static final String TAB = " ";
private static final String DOUBLE_TAB = TAB + TAB;
private static final int MAX_STACKTRACE_LINES = 10;
private static final String CAUSED_BY = "Caused by: ";
private static final String SUPPRESSED = "Suppressed: ";
private static final String CIRCULAR = "Circular reference: ";
final AtomicLong containersFound = new AtomicLong();
final AtomicLong containersStarted = new AtomicLong();
final AtomicLong containersSkipped = new AtomicLong();
final AtomicLong containersAborted = new AtomicLong();
final AtomicLong containersSucceeded = new AtomicLong();
final AtomicLong containersFailed = new AtomicLong();
final AtomicLong testsFound = new AtomicLong();
final AtomicLong testsStarted = new AtomicLong();
final AtomicLong testsSkipped = new AtomicLong();
final AtomicLong testsAborted = new AtomicLong();
final AtomicLong testsSucceeded = new AtomicLong();
final AtomicLong testsFailed = new AtomicLong();
private final TestPlan testPlan;
private final List failures = new ArrayList<>();
private final long timeStarted;
long timeFinished;
MutableTestExecutionSummary(TestPlan testPlan) {
this.testPlan = testPlan;
this.containersFound.set(testPlan.countTestIdentifiers(TestIdentifier::isContainer));
this.testsFound.set(testPlan.countTestIdentifiers(TestIdentifier::isTest));
this.timeStarted = System.currentTimeMillis();
}
void addFailure(TestIdentifier testIdentifier, Throwable throwable) {
this.failures.add(new DefaultFailure(testIdentifier, throwable));
}
@Override
public long getTimeStarted() {
return this.timeStarted;
}
@Override
public long getTimeFinished() {
return this.timeFinished;
}
@Override
public long getTotalFailureCount() {
return getTestsFailedCount() + getContainersFailedCount();
}
@Override
public long getContainersFoundCount() {
return this.containersFound.get();
}
@Override
public long getContainersStartedCount() {
return this.containersStarted.get();
}
@Override
public long getContainersSkippedCount() {
return this.containersSkipped.get();
}
@Override
public long getContainersAbortedCount() {
return this.containersAborted.get();
}
@Override
public long getContainersSucceededCount() {
return this.containersSucceeded.get();
}
@Override
public long getContainersFailedCount() {
return this.containersFailed.get();
}
@Override
public long getTestsFoundCount() {
return this.testsFound.get();
}
@Override
public long getTestsStartedCount() {
return this.testsStarted.get();
}
@Override
public long getTestsSkippedCount() {
return this.testsSkipped.get();
}
@Override
public long getTestsAbortedCount() {
return this.testsAborted.get();
}
@Override
public long getTestsSucceededCount() {
return this.testsSucceeded.get();
}
@Override
public long getTestsFailedCount() {
return this.testsFailed.get();
}
@Override
public void printTo(PrintWriter writer) {
// @formatter:off
writer.printf("%nTest run finished after %d ms%n"
+ "[%10d containers found ]%n"
+ "[%10d containers skipped ]%n"
+ "[%10d containers started ]%n"
+ "[%10d containers aborted ]%n"
+ "[%10d containers successful ]%n"
+ "[%10d containers failed ]%n"
+ "[%10d tests found ]%n"
+ "[%10d tests skipped ]%n"
+ "[%10d tests started ]%n"
+ "[%10d tests aborted ]%n"
+ "[%10d tests successful ]%n"
+ "[%10d tests failed ]%n"
+ "%n",
(this.timeFinished - this.timeStarted),
getContainersFoundCount(),
getContainersSkippedCount(),
getContainersStartedCount(),
getContainersAbortedCount(),
getContainersSucceededCount(),
getContainersFailedCount(),
getTestsFoundCount(),
getTestsSkippedCount(),
getTestsStartedCount(),
getTestsAbortedCount(),
getTestsSucceededCount(),
getTestsFailedCount()
);
// @formatter:on
writer.flush();
}
@Override
public void printFailuresTo(PrintWriter writer) {
if (getTotalFailureCount() > 0) {
writer.printf("%nFailures (%d):%n", getTotalFailureCount());
this.failures.forEach(failure -> {
writer.printf("%s%s%n", TAB, describeTest(failure.getTestIdentifier()));
printSource(writer, failure.getTestIdentifier());
writer.printf("%s=> %s%n", DOUBLE_TAB, failure.getException());
printStackTrace(writer, failure.getException(), MAX_STACKTRACE_LINES);
});
writer.flush();
}
}
@Override
public List getFailures() {
return Collections.unmodifiableList(failures);
}
private String describeTest(TestIdentifier testIdentifier) {
List descriptionParts = new ArrayList<>();
collectTestDescription(testIdentifier, descriptionParts);
return join(":", descriptionParts);
}
private void collectTestDescription(TestIdentifier identifier, List descriptionParts) {
descriptionParts.add(0, identifier.getDisplayName());
this.testPlan.getParent(identifier).ifPresent(parent -> collectTestDescription(parent, descriptionParts));
}
private void printSource(PrintWriter writer, TestIdentifier testIdentifier) {
testIdentifier.getSource().ifPresent(source -> writer.printf("%s%s%n", DOUBLE_TAB, source));
}
private void printStackTrace(PrintWriter writer, Throwable throwable, int max) {
if (throwable.getCause() != null
|| (throwable.getSuppressed() != null && throwable.getSuppressed().length > 0)) {
max = max / 2;
}
printStackTrace(writer, new StackTraceElement[] {}, throwable, "", DOUBLE_TAB + " ", new HashSet<>(), max);
writer.flush();
}
private void printStackTrace(PrintWriter writer, StackTraceElement[] parentTrace, Throwable throwable,
String caption, String indentation, Set seenThrowables, int max) {
if (seenThrowables.contains(throwable)) {
writer.printf("%s%s[%s%s]%n", indentation, TAB, CIRCULAR, throwable);
return;
}
seenThrowables.add(throwable);
StackTraceElement[] trace = throwable.getStackTrace();
if (parentTrace != null && parentTrace.length > 0) {
writer.printf("%s%s%s%n", indentation, caption, throwable);
}
int duplicates = numberOfCommonFrames(trace, parentTrace);
int numDistinctFrames = trace.length - duplicates;
int numDisplayLines = (numDistinctFrames > max) ? max : numDistinctFrames;
for (int i = 0; i < numDisplayLines; i++) {
writer.printf("%s%s%s%n", indentation, TAB, trace[i]);
}
if (trace.length > max || duplicates != 0) {
writer.printf("%s%s%s%n", indentation, TAB, "[...]");
}
for (Throwable suppressed : throwable.getSuppressed()) {
printStackTrace(writer, trace, suppressed, SUPPRESSED, indentation + TAB, seenThrowables, max);
}
if (throwable.getCause() != null) {
printStackTrace(writer, trace, throwable.getCause(), CAUSED_BY, indentation, seenThrowables, max);
}
}
private int numberOfCommonFrames(StackTraceElement[] currentTrace, StackTraceElement[] parentTrace) {
int currentIndex = currentTrace.length - 1;
for (int parentIndex = parentTrace.length - 1; currentIndex >= 0
&& parentIndex >= 0; currentIndex--, parentIndex--) {
if (!currentTrace[currentIndex].equals(parentTrace[parentIndex])) {
break;
}
}
return currentTrace.length - 1 - currentIndex;
}
private static class DefaultFailure implements Failure {
private final TestIdentifier testIdentifier;
private final Throwable exception;
DefaultFailure(TestIdentifier testIdentifier, Throwable exception) {
this.testIdentifier = testIdentifier;
this.exception = exception;
}
@Override
public TestIdentifier getTestIdentifier() {
return testIdentifier;
}
@Override
public Throwable getException() {
return exception;
}
}
}