1 /** 2 * Copyright (c) 2004-2016 QOS.ch 3 * All rights reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sublicense, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be 14 * included in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 */ 25 package org.slf4j.nop; 26 27 import static org.junit.Assert.assertEquals; 28 29 import java.io.PrintStream; 30 import java.util.ArrayList; 31 import java.util.List; 32 import java.util.Random; 33 import java.util.concurrent.BrokenBarrierException; 34 import java.util.concurrent.CyclicBarrier; 35 import java.util.concurrent.atomic.AtomicLong; 36 37 import org.junit.After; 38 import org.junit.Before; 39 import org.junit.Test; 40 import org.slf4j.Logger; 41 import org.slf4j.LoggerFactory; 42 import org.slf4j.LoggerFactoryFriend; 43 44 public class MultithreadedInitializationTest { 45 46 final static int THREAD_COUNT = 4 + Runtime.getRuntime().availableProcessors() * 2; 47 48 private static final AtomicLong EVENT_COUNT = new AtomicLong(0); 49 50 final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1); 51 52 int diff = new Random().nextInt(10000); 53 String loggerName = "org.slf4j.impl.MultithreadedInitializationTest"; 54 private final PrintStream oldErr = System.err; 55 StringPrintStream sps = new StringPrintStream(oldErr); 56 57 @Before setup()58 public void setup() { 59 LoggerFactoryFriend.reset(); 60 System.setErr(sps); 61 } 62 63 @After tearDown()64 public void tearDown() throws Exception { 65 LoggerFactoryFriend.reset(); 66 System.setErr(oldErr); 67 } 68 69 @Test multiThreadedInitialization()70 public void multiThreadedInitialization() throws InterruptedException, BrokenBarrierException { 71 System.out.println("THREAD_COUNT=" + THREAD_COUNT); 72 LoggerAccessingThread[] accessors = harness(); 73 74 for (LoggerAccessingThread accessor : accessors) { 75 EVENT_COUNT.getAndIncrement(); 76 accessor.logger.info("post harness"); 77 } 78 79 Logger logger = LoggerFactory.getLogger(loggerName + ".slowInitialization-" + diff); 80 logger.info("hello"); 81 EVENT_COUNT.getAndIncrement(); 82 83 assertEquals(0, sps.stringList.size()); 84 } 85 harness()86 private static LoggerAccessingThread[] harness() throws InterruptedException, BrokenBarrierException { 87 LoggerAccessingThread[] threads = new LoggerAccessingThread[THREAD_COUNT]; 88 final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1); 89 for (int i = 0; i < THREAD_COUNT; i++) { 90 threads[i] = new LoggerAccessingThread(barrier, i); 91 threads[i].start(); 92 } 93 94 barrier.await(); 95 for (int i = 0; i < THREAD_COUNT; i++) { 96 threads[i].join(); 97 } 98 return threads; 99 } 100 101 static class LoggerAccessingThread extends Thread { 102 final CyclicBarrier barrier; 103 Logger logger; 104 int count; 105 LoggerAccessingThread(CyclicBarrier barrier, int count)106 LoggerAccessingThread(CyclicBarrier barrier, int count) { 107 this.barrier = barrier; 108 this.count = count; 109 } 110 run()111 public void run() { 112 try { 113 barrier.await(); 114 } catch (Exception e) { 115 e.printStackTrace(); 116 } 117 logger = LoggerFactory.getLogger(this.getClass().getName() + "-" + count); 118 logger.info("in run method"); 119 EVENT_COUNT.getAndIncrement(); 120 } 121 }; 122 123 public static class StringPrintStream extends PrintStream { 124 125 public static final String LINE_SEP = System.getProperty("line.separator"); 126 PrintStream other; 127 List<String> stringList = new ArrayList<>(); 128 StringPrintStream(PrintStream ps)129 public StringPrintStream(PrintStream ps) { 130 super(ps); 131 other = ps; 132 } 133 print(String s)134 public void print(String s) { 135 other.print(s); 136 stringList.add(s); 137 } 138 println(String s)139 public void println(String s) { 140 other.println(s); 141 stringList.add(s); 142 } 143 println(Object o)144 public void println(Object o) { 145 other.println(o); 146 stringList.add(o.toString()); 147 } 148 }; 149 150 } 151