001package org.slf4j.testHarness; 002 003import static org.junit.Assert.assertTrue; 004import static org.junit.Assert.fail; 005 006import java.util.ArrayList; 007import java.util.Collections; 008import java.util.List; 009import java.util.concurrent.BrokenBarrierException; 010import java.util.concurrent.CyclicBarrier; 011import java.util.concurrent.atomic.AtomicLong; 012 013import org.junit.Test; 014import org.slf4j.Logger; 015import org.slf4j.LoggerAccessingThread; 016import org.slf4j.LoggerFactory; 017import org.slf4j.event.EventRecodingLogger; 018import org.slf4j.helpers.SubstituteLogger; 019 020abstract public class MultithreadedInitializationTest { 021 final protected static int THREAD_COUNT = 4 + Runtime.getRuntime().availableProcessors() * 2; 022 023 private final List<Logger> createdLoggers = Collections.synchronizedList(new ArrayList<>()); 024 025 final protected AtomicLong eventCount = new AtomicLong(0); 026 final private CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1); 027 028 @Test 029 public void multiThreadedInitialization() throws InterruptedException, BrokenBarrierException { 030 @SuppressWarnings("unused") 031 LoggerAccessingThread[] accessors = harness(); 032 033 Logger logger = LoggerFactory.getLogger(getClass().getName()); 034 logger.info("hello"); 035 eventCount.getAndIncrement(); 036 037 assertAllSubstLoggersAreFixed(); 038 long recordedEventCount = getRecordedEventCount(); 039 int LENIENCY_COUNT = 21; 040 041 long expectedEventCount = eventCount.get() + extraLogEvents(); 042 043 assertTrue(expectedEventCount + " >= " + recordedEventCount, expectedEventCount >= recordedEventCount); 044 assertTrue(expectedEventCount + " < " + recordedEventCount + "+" + LENIENCY_COUNT, expectedEventCount < recordedEventCount + LENIENCY_COUNT); 045 } 046 047 abstract protected long getRecordedEventCount(); 048 049 protected int extraLogEvents() { 050 return 0; 051 } 052 053 private void assertAllSubstLoggersAreFixed() { 054 for (Logger logger : createdLoggers) { 055 if (logger instanceof SubstituteLogger) { 056 SubstituteLogger substLogger = (SubstituteLogger) logger; 057 if (substLogger.delegate() instanceof EventRecodingLogger) 058 fail("substLogger " + substLogger.getName() + " has a delegate of type EventRecodingLogger"); 059 } 060 } 061 } 062 063 private LoggerAccessingThread[] harness() throws InterruptedException, BrokenBarrierException { 064 LoggerAccessingThread[] threads = new LoggerAccessingThread[THREAD_COUNT]; 065 for (int i = 0; i < THREAD_COUNT; i++) { 066 threads[i] = new LoggerAccessingThread(barrier, createdLoggers, i, eventCount); 067 threads[i].start(); 068 } 069 070 // trigger barrier 071 barrier.await(); 072 073 for (int i = 0; i < THREAD_COUNT; i++) { 074 threads[i].join(); 075 } 076 077 return threads; 078 } 079}