1 package org.slf4j.helpers;
2
3 import static org.junit.Assert.assertTrue;
4 import static org.junit.Assert.fail;
5
6 import java.util.ArrayList;
7 import java.util.Collections;
8 import java.util.List;
9 import java.util.Random;
10 import java.util.concurrent.BrokenBarrierException;
11 import java.util.concurrent.CyclicBarrier;
12 import java.util.concurrent.atomic.AtomicLong;
13
14 import org.junit.Test;
15 import org.slf4j.Logger;
16 import org.slf4j.LoggerAccessingThread;
17 import org.slf4j.LoggerFactory;
18 import org.slf4j.event.EventRecodingLogger;
19
20 abstract public class MultithreadedInitializationTest {
21 final protected static int THREAD_COUNT = 4 + Runtime.getRuntime().availableProcessors() * 2;
22
23 private final List<Logger> createdLoggers = Collections.synchronizedList(new ArrayList<Logger>());
24
25 final private AtomicLong eventCount = new AtomicLong(0);
26 final private CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
27
28 int diff = new Random().nextInt(10000);
29
30 @Test
31 public void multiThreadedInitialization() throws InterruptedException, BrokenBarrierException {
32 @SuppressWarnings("unused")
33 LoggerAccessingThread[] accessors = harness();
34
35 Logger logger = LoggerFactory.getLogger(getClass().getName());
36 logger.info("hello");
37 eventCount.getAndIncrement();
38
39 assertAllSubstLoggersAreFixed();
40 long recordedEventCount = getRecordedEventCount();
41 int LENIENCY_COUNT = 16;
42
43 long expectedEventCount = eventCount.get() + extraLogEvents();
44
45 assertTrue(expectedEventCount + " >= " + recordedEventCount, expectedEventCount >= recordedEventCount);
46 assertTrue(expectedEventCount + " < " + recordedEventCount + "+" + LENIENCY_COUNT, expectedEventCount < recordedEventCount + LENIENCY_COUNT);
47 }
48
49 abstract protected long getRecordedEventCount();
50
51 protected int extraLogEvents() {
52 return 0;
53 }
54
55 private void assertAllSubstLoggersAreFixed() {
56 for (Logger logger : createdLoggers) {
57 if (logger instanceof SubstituteLogger) {
58 SubstituteLogger substLogger = (SubstituteLogger) logger;
59 if (substLogger.delegate() instanceof EventRecodingLogger)
60 fail("substLogger " + substLogger.getName() + " has a delegate of type EventRecodingLogger");
61 }
62 }
63 }
64
65 private LoggerAccessingThread[] harness() throws InterruptedException, BrokenBarrierException {
66 LoggerAccessingThread[] threads = new LoggerAccessingThread[THREAD_COUNT];
67 for (int i = 0; i < THREAD_COUNT; i++) {
68 threads[i] = new LoggerAccessingThread(barrier, createdLoggers, i, eventCount);
69 threads[i].start();
70 }
71
72
73 barrier.await();
74
75 for (int i = 0; i < THREAD_COUNT; i++) {
76 threads[i].join();
77 }
78
79 return threads;
80 }
81 }