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