001package org.slf4j.helpers; 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.Random; 010import java.util.concurrent.BrokenBarrierException; 011import java.util.concurrent.CyclicBarrier; 012import java.util.concurrent.atomic.AtomicLong; 013 014import org.junit.Test; 015import org.slf4j.Logger; 016import org.slf4j.LoggerAccessingThread; 017import org.slf4j.LoggerFactory; 018import org.slf4j.event.EventRecodingLogger; 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<Logger>()); 024 025 final private AtomicLong eventCount = new AtomicLong(0); 026 final private CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1); 027 028 int diff = new Random().nextInt(10000); 029 030 @Test 031 public void multiThreadedInitialization() throws InterruptedException, BrokenBarrierException { 032 @SuppressWarnings("unused") 033 LoggerAccessingThread[] accessors = harness(); 034 035 Logger logger = LoggerFactory.getLogger(getClass().getName()); 036 logger.info("hello"); 037 eventCount.getAndIncrement(); 038 039 assertAllSubstLoggersAreFixed(); 040 long recordedEventCount = getRecordedEventCount(); 041 int LENIENCY_COUNT = 16; 042 043 long expectedEventCount = eventCount.get() + extraLogEvents(); 044 045 assertTrue(expectedEventCount + " >= " + recordedEventCount, expectedEventCount >= recordedEventCount); 046 assertTrue(expectedEventCount + " < " + recordedEventCount + "+" + LENIENCY_COUNT, expectedEventCount < recordedEventCount + LENIENCY_COUNT); 047 } 048 049 abstract protected long getRecordedEventCount(); 050 051 protected int extraLogEvents() { 052 return 0; 053 } 054 055 private void assertAllSubstLoggersAreFixed() { 056 for (Logger logger : createdLoggers) { 057 if (logger instanceof SubstituteLogger) { 058 SubstituteLogger substLogger = (SubstituteLogger) logger; 059 if (substLogger.delegate() instanceof EventRecodingLogger) 060 fail("substLogger " + substLogger.getName() + " has a delegate of type EventRecodingLogger"); 061 } 062 } 063 } 064 065 private LoggerAccessingThread[] harness() throws InterruptedException, BrokenBarrierException { 066 LoggerAccessingThread[] threads = new LoggerAccessingThread[THREAD_COUNT]; 067 for (int i = 0; i < THREAD_COUNT; i++) { 068 threads[i] = new LoggerAccessingThread(barrier, createdLoggers, i, eventCount); 069 threads[i].start(); 070 } 071 072 // trigger barrier 073 barrier.await(); 074 075 for (int i = 0; i < THREAD_COUNT; i++) { 076 threads[i].join(); 077 } 078 079 return threads; 080 } 081}