package org.slf4j.impl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.util.List;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicLong;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.LoggerFactoryFriend;
import ch.qos.logback.classic.ClassicTestConstants;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.util.ContextInitializer;
import ch.qos.logback.core.read.ListAppender;
public class MultithreadedInitializationTest {
final static int THREAD_COUNT = 4 + Runtime.getRuntime().availableProcessors() * 2;
private static AtomicLong EVENT_COUNT = new AtomicLong(0);
final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
int diff = new Random().nextInt(10000);
String loggerName = "org.slf4j.impl.MultithreadedInitializationTest";
@Before
public void setUp() throws Exception {
System.setProperty(ContextInitializer.CONFIG_FILE_PROPERTY, ClassicTestConstants.INPUT_PREFIX + "listAppender.xml");
LoggerFactoryFriend.reset();
}
@After
public void tearDown() throws Exception {
System.clearProperty(ContextInitializer.CONFIG_FILE_PROPERTY);
}
@Test
public void multiThreadedInitialization() throws InterruptedException, BrokenBarrierException {
LoggerAccessingThread[] accessors = harness();
for (LoggerAccessingThread accessor : accessors) {
EVENT_COUNT.getAndIncrement();
accessor.logger.info("post harness");
}
Logger logger = LoggerFactory.getLogger(loggerName + ".slowInitialization-" + diff);
logger.info("hello");
EVENT_COUNT.getAndIncrement();
List<ILoggingEvent> events = getRecordedEvents();
assertEquals(EVENT_COUNT.get(), events.size());
}
private List<ILoggingEvent> getRecordedEvents() {
ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
ListAppender<ILoggingEvent> la = (ListAppender<ILoggingEvent>) root.getAppender("LIST");
assertNotNull(la);
return la.list;
}
private static LoggerAccessingThread[] harness() throws InterruptedException, BrokenBarrierException {
LoggerAccessingThread[] threads = new LoggerAccessingThread[THREAD_COUNT];
final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
for (int i = 0; i < THREAD_COUNT; i++) {
threads[i] = new LoggerAccessingThread(barrier, i);
threads[i].start();
}
barrier.await();
for (int i = 0; i < THREAD_COUNT; i++) {
threads[i].join();
}
return threads;
}
static class LoggerAccessingThread extends Thread {
final CyclicBarrier barrier;
Logger logger;
int count;
LoggerAccessingThread(CyclicBarrier barrier, int count) {
this.barrier = barrier;
this.count = count;
}
public void run() {
try {
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
logger = LoggerFactory.getLogger(this.getClass().getName() + "-" + count);
logger.info("in run method");
EVENT_COUNT.getAndIncrement();
}
};
}