Skip to content

Commit

Permalink
remove multi-suite support in EventDispatcher and RichLogger
Browse files Browse the repository at this point in the history
These types map 1:1 to suites/TaskDefs, which means that the complexity
of some of the data structures can be avoided.
Addresses point 2) in scalameta#399, see that ticket for more details.
  • Loading branch information
jenshalm committed Aug 10, 2021
1 parent 833c6a4 commit e651d11
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;

import org.junit.runner.Description;
import org.junit.runner.Result;
Expand All @@ -20,16 +21,14 @@ final class EventDispatcher extends RunListener
{
private final RichLogger logger;
private final Set<Description> reported = Collections.newSetFromMap(new ConcurrentHashMap<Description, Boolean>());
private final Set<String> reportedSuites = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());
private final AtomicBoolean suiteStartReported = new AtomicBoolean(false);
private final ConcurrentHashMap<String, Long> startTimes = new ConcurrentHashMap<String, Long>();
private final EventHandler handler;
private final RunSettings settings;
private final Fingerprint fingerprint;
private final String taskInfo;
private final RunStatistics runStatistics;

private final static Description TEST_RUN = Description.createTestDescription("Test", "run");

EventDispatcher(RichLogger logger, EventHandler handler, RunSettings settings, Fingerprint fingerprint,
Description taskDescription, RunStatistics runStatistics)
{
Expand Down Expand Up @@ -70,7 +69,7 @@ public void testAssumptionFailure(final Failure failure)
postIfFirst(failure.getDescription(), new ErrorEvent(failure, Status.Skipped) {
void logTo(RichLogger logger) {
if (settings.verbose) {
logger.info(failure.getDescription(), Ansi.c("==> i " + failure.getDescription().getMethodName(), WARNMSG));
logger.info(Ansi.c("==> i " + failure.getDescription().getMethodName(), WARNMSG));
}
}
});
Expand All @@ -93,7 +92,7 @@ public void testFailure(final Failure failure)
}
postIfFirst(failure.getDescription(), new ErrorEvent(failure, Status.Failure) {
void logTo(RichLogger logger) {
logger.error( failure.getDescription(), settings.buildTestResult(Status.Failure) +ansiName+" "+ durationSuffix() + " " + ansiMsg, error);
logger.error(settings.buildTestResult(Status.Failure) +ansiName+" "+ durationSuffix() + " " + ansiMsg, error);
}
});
}
Expand All @@ -104,18 +103,17 @@ public void testFinished(Description desc)
{
postIfFirst(desc, new InfoEvent(desc, Status.Success) {
void logTo(RichLogger logger) {
logger.info(desc, settings.buildTestResult(Status.Success) + Ansi.c(desc.getMethodName(), SUCCESS1) + durationSuffix());
logger.info(settings.buildTestResult(Status.Success) + Ansi.c(desc.getMethodName(), SUCCESS1) + durationSuffix());
}
});
logger.popCurrentTestClassName();
}

@Override
public void testIgnored(Description desc)
{
postIfFirst(desc, new InfoEvent(desc, Status.Skipped) {
void logTo(RichLogger logger) {
logger.warn(desc, settings.buildTestResult(Status.Ignored) + ansiName+" ignored" + durationSuffix());
logger.warn(settings.buildTestResult(Status.Ignored) + ansiName+" ignored" + durationSuffix());
}
});
}
Expand All @@ -125,30 +123,26 @@ void logTo(RichLogger logger) {
public void testSuiteStarted(Description desc)
{
if (desc == null || desc.getClassName() == null || desc.getClassName().equals("null")) return;
reportedSuites.add(desc.getClassName());
logger.info(desc, c(desc.getClassName() + ":", SUCCESS1));
if (suiteStartReported.compareAndSet(false, true)) logger.info(c(desc.getClassName() + ":", SUCCESS1));
}


@Override
public void testStarted(Description desc)
{
recordStartTime(desc);
if (reportedSuites.add(desc.getClassName())) {
testSuiteStarted(desc);
}
logger.pushCurrentTestClassName(desc.getClassName());
testSuiteStarted(desc);
if (settings.verbose) {
logger.info(desc, settings.buildPlainName(desc) + " started");
logger.info(settings.buildPlainName(desc) + " started");
}
}

private void recordStartTime(Description description) {
startTimes.putIfAbsent(settings.buildPlainName(description), System.currentTimeMillis());
startTimes.putIfAbsent(description.getMethodName(), System.currentTimeMillis());
}

private Long elapsedTime(Description description) {
Long startTime = startTimes.get(settings.buildPlainName(description));
Long startTime = startTimes.get(description.getMethodName());
if( startTime == null ) {
return 0l;
} else {
Expand All @@ -160,34 +154,36 @@ private Long elapsedTime(Description description) {
public void testRunFinished(Result result)
{
if (settings.verbose) {
logger.info(TEST_RUN, "Test run " +taskInfo+" finished: "+
logger.info("Test run " +taskInfo+" finished: "+
result.getFailureCount()+" failed" +
", " +
result.getIgnoreCount()+" ignored" +
", "+result.getRunCount()+" total, "+(result.getRunTime()/1000.0)+"s") ;
logger.flush();
}
runStatistics.addTime(result.getRunTime());
logger.flush(TEST_RUN);
}

@Override
public void testSuiteFinished(Description description) throws Exception {
logger.flush(description);
logger.flush();
}

@Override
public void testRunStarted(Description desc)
{
if (settings.verbose) {
logger.info(desc, taskInfo + " started");
logger.info(taskInfo + " started");
logger.flush();
}
}

void testExecutionFailed(String testName, Throwable err)
{
post(new Event(Ansi.c(testName, Ansi.ERRMSG), settings.buildErrorMessage(err), Status.Error, 0L, err) {
void logTo(RichLogger logger) {
logger.error(TEST_RUN, ansiName+" failed: "+ansiMsg, error);
logger.error(ansiName+" failed: "+ansiMsg, error);
logger.flush();
}
});
}
Expand Down Expand Up @@ -220,7 +216,7 @@ private static void trimStackTrace(Throwable ex, String fromClassName, String to
int end = stackTrace.length - 1;
StackTraceElement last = stackTrace[end];
if (last.getClassName() != null && last.getClassName().equals(fromClassName)) {
for (int i = 0; end >= 0; end--) {
for (; end >= 0; end--) {
StackTraceElement e = stackTrace[end];
if (e.getClassName().equals(toClassName)) {
break;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
package munit.internal.junitinterface;

import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;

import org.junit.runner.Description;
import sbt.testing.Logger;
import static munit.internal.junitinterface.Ansi.*;

Expand All @@ -20,91 +14,81 @@ final class RichLogger
private final Logger[] loggers;
private final RunSettings settings;
private final JUnitRunner runner;
/* The top element is the test class of the currently executing test */
private final Stack<String> currentTestClassName = new Stack<String>();
private final String testClassName;
private final Map<String, Boolean> highlightedCache = new HashMap<>();
private final ConcurrentHashMap<String, ConcurrentLinkedDeque<String>> buffers = new ConcurrentHashMap<>();
private final ConcurrentLinkedDeque<String> buffer = new ConcurrentLinkedDeque<>();

RichLogger(Logger[] loggers, RunSettings settings, String testClassName, JUnitRunner runner)
{
this.loggers = loggers;
this.settings = settings;
this.runner = runner;
currentTestClassName.push(testClassName);
this.testClassName = testClassName;
}

void pushCurrentTestClassName(String s) { currentTestClassName.push(s); }

void popCurrentTestClassName()
{
if(currentTestClassName.size() > 1) currentTestClassName.pop();
}

void error(Description desc, String s)
void error(String s)
{
if (settings.useSbtLoggers) {
for (Logger l : loggers)
if (settings.color && l.ansiCodesSupported()) l.error(s);
else l.error(filterAnsi(s));
} else if (settings.useBufferedLoggers) {
bufferMessage(desc, s);
bufferMessage(s);
} else {
System.out.println(s);
}
}

void error(Description desc, String s, Throwable t)
void error(String s, Throwable t)
{
error(desc, s);
if(t != null && (settings.logAssert || !(t instanceof AssertionError))) logStackTrace(desc, t);
error(s);
if(t != null && (settings.logAssert || !(t instanceof AssertionError))) logStackTrace(t);
}

void info(Description desc, String s)
void info(String s)
{
if (settings.useSbtLoggers) {
for (Logger l : loggers)
if (settings.color && l.ansiCodesSupported()) l.info(s);
else l.info(filterAnsi(s));
} else if (settings.useBufferedLoggers) {
bufferMessage(desc, s);
bufferMessage(s);
} else {
System.out.println(s);
}
}

void warn(Description desc, String s)
void warn(String s)
{
if (settings.useSbtLoggers) {
for (Logger l : loggers)
if (settings.color && l.ansiCodesSupported()) l.warn(s);
else l.warn(filterAnsi(s));
} else if (settings.useBufferedLoggers) {
bufferMessage(desc, s);
bufferMessage(s);
} else {
System.out.println(s);
}
}

void flush(Description desc) {
ConcurrentLinkedDeque<String> logs = buffers.remove(String.valueOf(desc.getClassName()));
if (logs != null) {
System.out.println(String.join("\n", logs));
void flush() {
if (!buffer.isEmpty()) {
System.out.println(String.join("\n", buffer));
buffer.clear();
}
}

private void bufferMessage(Description desc, String message) {
ConcurrentLinkedDeque<String> logs = buffers.computeIfAbsent(String.valueOf(desc.getClassName()), d -> new ConcurrentLinkedDeque<>());
logs.addLast(message);
private void bufferMessage(String message) {
buffer.addLast(message);
}
private void logStackTrace(Description desc, Throwable t)
private void logStackTrace(Throwable t)
{
StackTraceElement[] trace = t.getStackTrace();
String testClassName = currentTestClassName.peek();
String testFileName = settings.color ? findTestFileName(trace, testClassName) : null;
logStackTracePart(desc, trace, trace.length-1, 0, t, testClassName, testFileName);
logStackTracePart(trace, trace.length-1, 0, t, testFileName);
}

private void logStackTracePart(Description desc, StackTraceElement[] trace, int m, int framesInCommon, Throwable t, String testClassName, String testFileName)
private void logStackTracePart(StackTraceElement[] trace, int m, int framesInCommon, Throwable t, String testFileName)
{
final int m0 = m;
int top = 0;
Expand All @@ -130,22 +114,22 @@ private void logStackTracePart(Description desc, StackTraceElement[] trace, int
}
for(int i=top; i<=m; i++) {
if (!trace[i].getClassName().startsWith("scala.runtime."))
error(desc, stackTraceElementToString(trace[i], testClassName, testFileName));
error(stackTraceElementToString(trace[i], testFileName));
}
if(m0 != m)
{
// skip junit-related frames
error(desc, " ...");
error(" ...");
}
else if(framesInCommon != 0)
{
// skip frames that were in the previous trace too
error(desc, " ... " + framesInCommon + " more");
error(" ... " + framesInCommon + " more");
}
logStackTraceAsCause(desc, trace, t.getCause(), testClassName, testFileName);
logStackTraceAsCause(trace, t.getCause(), testFileName);
}

private void logStackTraceAsCause(Description desc, StackTraceElement[] causedTrace, Throwable t, String testClassName, String testFileName)
private void logStackTraceAsCause(StackTraceElement[] causedTrace, Throwable t, String testFileName)
{
if(t == null) return;
StackTraceElement[] trace = t.getStackTrace();
Expand All @@ -155,8 +139,8 @@ private void logStackTraceAsCause(Description desc, StackTraceElement[] causedTr
m--;
n--;
}
error(desc, "Caused by: " + t);
logStackTracePart(desc, trace, m, trace.length-1-m, t, testClassName, testFileName);
error("Caused by: " + t);
logStackTracePart(trace, m, trace.length-1-m, t, testFileName);
}

private String findTestFileName(StackTraceElement[] trace, String testClassName)
Expand Down Expand Up @@ -184,7 +168,7 @@ private boolean isHighlighted(String className) {
}
}

private String stackTraceElementToString(StackTraceElement e, String testClassName, String testFileName)
private String stackTraceElementToString(StackTraceElement e, String testFileName)
{
boolean highlight = settings.color && (
testClassName.equals(e.getClassName()) ||
Expand Down

0 comments on commit e651d11

Please sign in to comment.