package jetbrains.mps.testbench.junit; /*Generated by MPS */ import org.apache.log4j.Level; import java.util.regex.Pattern; import jetbrains.mps.testbench.util.CachingAppender; import java.util.Map; import org.junit.runner.Description; import java.util.HashMap; import jetbrains.mps.testbench.util.ThreadWatcher; import org.junit.runner.notification.RunNotifier; import java.util.List; import java.util.ArrayList; import org.junit.runner.notification.StoppedByUserException; import org.junit.runner.notification.Failure; import org.apache.log4j.Logger; /** * fyodor, Aug 18, 2010 */ public class WatchingRunNotifier extends DelegatingRunNotifier { private static final Level DEFAULT_WATCH_LOGGER_LEVEL = Level.ERROR; private static final Pattern EXECUTION_LIMIT_FAILED_PATTERN = Pattern.compile("(\\d)* ms execution limit failed for:[^,]*,(\\d*)(\\s)*"); private static final Pattern WARN_PATTERN_MULTILINE = Pattern.compile("\\[([\\d\\s])*\\](\\s)*WARN.*:\\n[^\\[^\\s].*"); private static final Pattern WARN_PATTERN = Pattern.compile("\\[([\\d\\s])*\\](\\s)*WARN.*"); private final Level myWatchLevel; private final IgnoringPatternErrorStream myErrorCachingStream; private CachingAppender myCachingAppender; private Map<Description, Object> myTestsToIgnore = new HashMap<Description, Object>(); private ThreadWatcher myThreadWatcher; public WatchingRunNotifier(RunNotifier delegate) { this(delegate, DEFAULT_WATCH_LOGGER_LEVEL, true); } public WatchingRunNotifier(RunNotifier delegate, Level watchLevel, boolean ignoreWarnings) { super(delegate); myWatchLevel = watchLevel; myErrorCachingStream = new IgnoringPatternErrorStream(getPatternsToIgnore(ignoreWarnings)); } private List<Pattern> getPatternsToIgnore(boolean ignoreWarnings) { List<Pattern> result = new ArrayList<Pattern>(); result.add(EXECUTION_LIMIT_FAILED_PATTERN); if (ignoreWarnings) { result.add(WARN_PATTERN_MULTILINE); result.add(WARN_PATTERN); } return result; } public void dispose() { } @Override public void fireTestStarted(Description description) throws StoppedByUserException { super.fireTestStarted(description); try { beforeTest(description); } catch (Throwable e) { super.fireTestFailure(new Failure(description, e)); } } @Override public void fireTestFinished(Description description) { try { afterTest(description); } catch (Throwable e) { super.fireTestFailure(new Failure(description, e)); } super.fireTestFinished(description); } @Override public void fireTestFailure(Failure failure) { myTestsToIgnore.put(failure.getDescription(), Boolean.TRUE); super.fireTestFailure(failure); } @Override public void fireTestAssumptionFailed(Failure failure) { myTestsToIgnore.put(failure.getDescription(), Boolean.TRUE); super.fireTestAssumptionFailed(failure); } @Override public void fireTestIgnored(Description description) { myTestsToIgnore.put(description, Boolean.TRUE); super.fireTestIgnored(description); } private void beforeTest(Description desc) { myErrorCachingStream.reRoute(); myCachingAppender = new CachingAppender(myWatchLevel); Logger.getRootLogger().addAppender(myCachingAppender); ExpectLogEvent expectEvent = desc.getAnnotation(ExpectLogEvent.class); if (expectEvent != null) { for (String text : expectEvent.text()) { myCachingAppender.expectEvent(expectEvent.level(), text); } } IgnoreLogEvents ignoreEvents = desc.getAnnotation(IgnoreLogEvents.class); if (ignoreEvents != null) { myTestsToIgnore.put(desc, Boolean.TRUE); } myThreadWatcher = new ThreadWatcher(true); } private void afterTest(Description desc) { myThreadWatcher.waitUntilSettled(15000); myErrorCachingStream.reset(); myCachingAppender.sealEvents(); Logger.getRootLogger().removeAppender(myCachingAppender); Failure fail = null; if (!(myTestsToIgnore.containsKey(desc))) { if (myErrorCachingStream.isNotEmpty() || myCachingAppender.isNotEmpty() || myThreadWatcher.isNotEmpty()) { fail = new Failure(desc, new UncleanTestExecutionException(myErrorCachingStream, myCachingAppender, myThreadWatcher)); } } myErrorCachingStream.clear(); if (fail != null) { super.fireTestFailure(fail); } } }