package org.junit.runner.notification;

import org.junit.runner.Description;
import org.junit.runner.Result;

Thread-safe decorator for RunListener implementations that synchronizes calls to the delegate.

This class synchronizes all listener calls on a RunNotifier instance. This is done because prior to JUnit 4.12, all listeners were called in a synchronized block in RunNotifier, so no two listeners were ever called concurrently. If we instead made the methods here sychronized, clients that added multiple listeners that called common code might see issues due to the reduced synchronization.

Author:Tibor Digana (tibor17), Kevin Cooney (kcooney)
See Also:
Since:4.12
/** * Thread-safe decorator for {@link RunListener} implementations that synchronizes * calls to the delegate. * * <p>This class synchronizes all listener calls on a RunNotifier instance. This is done because * prior to JUnit 4.12, all listeners were called in a synchronized block in RunNotifier, * so no two listeners were ever called concurrently. If we instead made the methods here * sychronized, clients that added multiple listeners that called common code might see * issues due to the reduced synchronization. * * @author Tibor Digana (tibor17) * @author Kevin Cooney (kcooney) * @since 4.12 * * @see RunNotifier */
@RunListener.ThreadSafe final class SynchronizedRunListener extends RunListener { private final RunListener listener; private final Object monitor; SynchronizedRunListener(RunListener listener, Object monitor) { this.listener = listener; this.monitor = monitor; } @Override public void testRunStarted(Description description) throws Exception { synchronized (monitor) { listener.testRunStarted(description); } } @Override public void testRunFinished(Result result) throws Exception { synchronized (monitor) { listener.testRunFinished(result); } } @Override public void testStarted(Description description) throws Exception { synchronized (monitor) { listener.testStarted(description); } } @Override public void testFinished(Description description) throws Exception { synchronized (monitor) { listener.testFinished(description); } } @Override public void testFailure(Failure failure) throws Exception { synchronized (monitor) { listener.testFailure(failure); } } @Override public void testAssumptionFailure(Failure failure) { synchronized (monitor) { listener.testAssumptionFailure(failure); } } @Override public void testIgnored(Description description) throws Exception { synchronized (monitor) { listener.testIgnored(description); } } @Override public int hashCode() { return listener.hashCode(); } @Override public boolean equals(Object other) { if (this == other) { return true; } if (!(other instanceof SynchronizedRunListener)) { return false; } SynchronizedRunListener that = (SynchronizedRunListener) other; return listener.equals(that.listener); } @Override public String toString() { return listener.toString() + " (with synchronization wrapper)"; } }