-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Beginning of Surefire Emulator (#61)
* makes all sleep ms different from each other * create surefire emulator * inject logger in the emulator and add our first assertion
- Loading branch information
1 parent
f942700
commit 83e7b0a
Showing
10 changed files
with
260 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 2 additions & 1 deletion
3
src/test/java/DynamicExampleTest.java → ...n/plugin/surefire/DynamicExampleTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 2 additions & 0 deletions
2
src/test/java/ExampleTest.java → ...he/maven/plugin/surefire/ExampleTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 2 additions & 0 deletions
2
src/test/java/LongNameExampleTest.java → .../plugin/surefire/LongNameExampleTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 2 additions & 0 deletions
2
src/test/java/ParameterizedExampleTest.java → ...in/surefire/ParameterizedExampleTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
64 changes: 64 additions & 0 deletions
64
src/test/java/org/apache/maven/plugin/surefire/report/EmulatorLogger.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package org.apache.maven.plugin.surefire.report; | ||
|
||
import org.codehaus.plexus.logging.AbstractLogger; | ||
import org.codehaus.plexus.logging.Logger; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
// Copy from org.codehaus.plexus.logging.console.ConsoleLogger so we can extend it | ||
|
||
public class EmulatorLogger extends AbstractLogger { | ||
private static final String[] TAGS = {"[DEBUG] ", "[INFO] ", "[WARNING] ", "[ERROR] ", "[FATAL ERROR] "}; | ||
private final ArrayList<String> logs = new ArrayList<>(); | ||
|
||
public EmulatorLogger() { | ||
this(Logger.LEVEL_INFO, "console"); | ||
} | ||
|
||
public EmulatorLogger(int threshold, String name) { | ||
super(threshold, name); | ||
} | ||
|
||
public void debug(final String message, final Throwable throwable) { | ||
if (isDebugEnabled()) log(LEVEL_DEBUG, message, throwable); | ||
} | ||
|
||
public void info(final String message, final Throwable throwable) { | ||
if (isInfoEnabled()) log(LEVEL_INFO, message, throwable); | ||
} | ||
|
||
public void warn(final String message, final Throwable throwable) { | ||
if (isWarnEnabled()) log(LEVEL_WARN, message, throwable); | ||
} | ||
|
||
public void error(final String message, final Throwable throwable) { | ||
if (isErrorEnabled()) log(LEVEL_ERROR, message, throwable); | ||
} | ||
|
||
public void fatalError(final String message, final Throwable throwable) { | ||
if (isFatalErrorEnabled()) log(LEVEL_FATAL, message, throwable); | ||
} | ||
|
||
public Logger getChildLogger(final String name) { | ||
return this; | ||
} | ||
|
||
public void clearLogs() { | ||
System.out.println("Cleaning logs..."); | ||
logs.clear(); | ||
} | ||
|
||
public List<String> getLogList() { | ||
return logs; | ||
} | ||
|
||
private void log(final int level, final String message, final Throwable throwable) { | ||
logs.add(message); | ||
// System.out.println(TAGS[level].concat(message)); | ||
System.out.println(message); | ||
if (throwable != null) { | ||
throwable.printStackTrace(System.out); | ||
} | ||
} | ||
} |
134 changes: 134 additions & 0 deletions
134
src/test/java/org/apache/maven/plugin/surefire/report/SurefireEmulator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
package org.apache.maven.plugin.surefire.report; | ||
|
||
import org.apache.maven.plugin.surefire.log.PluginConsoleLogger; | ||
import org.apache.maven.surefire.api.report.RunMode; | ||
import org.apache.maven.surefire.api.report.SimpleReportEntry; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.DisplayNameGenerator; | ||
import org.junit.platform.commons.util.StringUtils; | ||
|
||
import java.lang.reflect.AnnotatedElement; | ||
import java.lang.reflect.Method; | ||
import java.util.*; | ||
import java.util.function.Function; | ||
import java.util.function.Supplier; | ||
import java.util.stream.Collectors; | ||
|
||
import static java.util.stream.Collectors.toList; | ||
import static org.junit.jupiter.api.DisplayNameGenerator.getDisplayNameGenerator; | ||
import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation; | ||
|
||
public class SurefireEmulator { | ||
|
||
private final EmulatorLogger emulatorLogger = new EmulatorLogger(); | ||
private final DisplayNameGenerator displayNameGenerator = getDisplayNameGenerator(DisplayNameGenerator.Standard.class); | ||
private final Utf8RecodingDeferredFileOutputStream stdout = new Utf8RecodingDeferredFileOutputStream("stdout"); | ||
private final Utf8RecodingDeferredFileOutputStream stderr = new Utf8RecodingDeferredFileOutputStream("stderr"); | ||
private final Class<?> clazz; | ||
private final ConsoleTreeReporter consoleTreeReporter; | ||
|
||
public SurefireEmulator(Class<?> clazz) { | ||
this(ReporterOptions.builder().build(), clazz); | ||
} | ||
|
||
public SurefireEmulator(ReporterOptions reporterOptions, Class<?> clazz) { | ||
this.clazz = clazz; | ||
this.consoleTreeReporter = new ConsoleTreeReporter(new PluginConsoleLogger(emulatorLogger), reporterOptions); | ||
} | ||
|
||
public List<String> run() { | ||
testsStarting(); | ||
testsCompleted(testsSucceeded()); | ||
return emulatorLogger.getLogList(); | ||
} | ||
|
||
private void testsCompleted(TestSetStats testSetStats) { | ||
List<WrappedReportEntry> completedWrappedEntries = | ||
getAllInnerClasses(clazz).stream() | ||
.map(this::simpleReportEntryGenerator) | ||
.map(this::wrappedReportEntryGenerator) | ||
.collect(toList()); | ||
|
||
//List's head needs to be with complete testSetStats | ||
completedWrappedEntries.stream().findFirst() | ||
.ifPresent(i -> consoleTreeReporter.testSetCompleted(i, testSetStats, null)); | ||
|
||
//List's tail goes with empty testSetStats | ||
completedWrappedEntries.stream().skip(1) | ||
.forEachOrdered(i -> consoleTreeReporter.testSetCompleted(i, new TestSetStats(false, false), null)); | ||
} | ||
|
||
private TestSetStats testsSucceeded() { | ||
TestSetStats testSetStats = new TestSetStats(false, true); | ||
getAllMethods(getAllInnerClasses(clazz)) | ||
.entrySet().stream() | ||
.flatMap((k) -> k.getValue().stream() | ||
.map(i -> this.simpleReportEntryGenerator(k.getKey(), i)) | ||
.map(this::wrappedReportEntryGenerator)) | ||
.forEachOrdered(testSetStats::testSucceeded); | ||
return testSetStats; | ||
} | ||
|
||
private void testsStarting() { | ||
getAllInnerClasses(clazz).stream() | ||
.map(this::simpleReportEntryGenerator) | ||
.forEachOrdered(consoleTreeReporter::testSetStarting); | ||
} | ||
|
||
private <T> SimpleReportEntry simpleReportEntryGenerator(Class<T> clazz) { | ||
return new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, clazz.getName(), getClassDisplayName(clazz), null, null); | ||
} | ||
|
||
private <T> SimpleReportEntry simpleReportEntryGenerator(Class<T> clazz, Method method) { | ||
return new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, clazz.getName(), getClassDisplayName(clazz), method.getName(), getMethodDisplayName(clazz, method)); | ||
} | ||
|
||
private WrappedReportEntry wrappedReportEntryGenerator(SimpleReportEntry simpleReportEntry) { | ||
return new WrappedReportEntry(simpleReportEntry, ReportEntryType.SUCCESS, 1, stdout, stderr); | ||
} | ||
|
||
private List<Class<?>> getAllInnerClasses(Class<?> clazz) { | ||
return getAllInnerClasses(clazz, new ArrayList<>()); | ||
} | ||
|
||
private List<Class<?>> getAllInnerClasses(Class<?> clazz, List<Class<?>> acc) { | ||
if (clazz.getDeclaredClasses().length == 0) { | ||
acc.add(clazz); | ||
return acc; | ||
} | ||
acc.add(clazz); | ||
acc.addAll(Arrays.stream(clazz.getDeclaredClasses()) | ||
.flatMap(i -> getAllInnerClasses(i, new ArrayList<>()).stream()) | ||
.collect(toList())); | ||
return acc; | ||
} | ||
|
||
private Map<Class<?>, List<Method>> getAllMethods(List<Class<?>> classes) { | ||
return classes.stream() | ||
.collect(Collectors.toMap(Function.identity(), | ||
i -> Arrays.asList(i.getDeclaredMethods()), | ||
(x, y) -> y, LinkedHashMap::new)); | ||
} | ||
|
||
// Got the methods below from JUnit Jupiter codebase DisplayNameUtils.java | ||
private String getDisplayName(AnnotatedElement element, Supplier<String> displayNameSupplier) { | ||
Optional<DisplayName> displayNameAnnotation = findAnnotation(element, DisplayName.class); | ||
if (displayNameAnnotation.isPresent()) { | ||
String displayName = displayNameAnnotation.get().value().trim(); | ||
if (!StringUtils.isBlank(displayName)) return displayName; | ||
} | ||
return displayNameSupplier.get(); | ||
} | ||
|
||
private <T> String getClassDisplayName(Class<T> clazz) { | ||
if (clazz.getEnclosingClass() == null) { | ||
return getDisplayName(clazz, () -> displayNameGenerator.generateDisplayNameForClass(clazz)); | ||
} else { | ||
return getDisplayName(clazz, () -> displayNameGenerator.generateDisplayNameForNestedClass(clazz)); | ||
} | ||
} | ||
|
||
private <T> String getMethodDisplayName(Class<T> clazz, Method method) { | ||
return getDisplayName(method, () -> displayNameGenerator.generateDisplayNameForMethod(clazz, method)); | ||
} | ||
} |