001/** 002 * Copyright (c) 2004-2016 QOS.ch 003 * All rights reserved. 004 * 005 * Permission is hereby granted, free of charge, to any person obtaining 006 * a copy of this software and associated documentation files (the 007 * "Software"), to deal in the Software without restriction, including 008 * without limitation the rights to use, copy, modify, merge, publish, 009 * distribute, sublicense, and/or sell copies of the Software, and to 010 * permit persons to whom the Software is furnished to do so, subject to 011 * the following conditions: 012 * 013 * The above copyright notice and this permission notice shall be 014 * included in all copies or substantial portions of the Software. 015 * 016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 017 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 018 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 019 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 020 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 021 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 022 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 023 * 024 */ 025package org.slf4j.nop; 026 027import static org.junit.Assert.assertEquals; 028 029import java.io.PrintStream; 030import java.util.ArrayList; 031import java.util.List; 032import java.util.Random; 033import java.util.concurrent.BrokenBarrierException; 034import java.util.concurrent.CyclicBarrier; 035import java.util.concurrent.atomic.AtomicLong; 036 037import org.junit.After; 038import org.junit.Before; 039import org.junit.Test; 040import org.slf4j.Logger; 041import org.slf4j.LoggerFactory; 042import org.slf4j.LoggerFactoryFriend; 043 044public class MultithreadedInitializationTest { 045 046 final static int THREAD_COUNT = 4 + Runtime.getRuntime().availableProcessors() * 2; 047 048 private static final AtomicLong EVENT_COUNT = new AtomicLong(0); 049 050 final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1); 051 052 int diff = new Random().nextInt(10000); 053 String loggerName = "org.slf4j.impl.MultithreadedInitializationTest"; 054 private final PrintStream oldErr = System.err; 055 StringPrintStream sps = new StringPrintStream(oldErr); 056 057 @Before 058 public void setup() { 059 LoggerFactoryFriend.reset(); 060 System.setErr(sps); 061 } 062 063 @After 064 public void tearDown() throws Exception { 065 LoggerFactoryFriend.reset(); 066 System.setErr(oldErr); 067 } 068 069 @Test 070 public void multiThreadedInitialization() throws InterruptedException, BrokenBarrierException { 071 System.out.println("THREAD_COUNT=" + THREAD_COUNT); 072 LoggerAccessingThread[] accessors = harness(); 073 074 for (LoggerAccessingThread accessor : accessors) { 075 EVENT_COUNT.getAndIncrement(); 076 accessor.logger.info("post harness"); 077 } 078 079 Logger logger = LoggerFactory.getLogger(loggerName + ".slowInitialization-" + diff); 080 logger.info("hello"); 081 EVENT_COUNT.getAndIncrement(); 082 083 assertEquals(0, sps.stringList.size()); 084 } 085 086 private static LoggerAccessingThread[] harness() throws InterruptedException, BrokenBarrierException { 087 LoggerAccessingThread[] threads = new LoggerAccessingThread[THREAD_COUNT]; 088 final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1); 089 for (int i = 0; i < THREAD_COUNT; i++) { 090 threads[i] = new LoggerAccessingThread(barrier, i); 091 threads[i].start(); 092 } 093 094 barrier.await(); 095 for (int i = 0; i < THREAD_COUNT; i++) { 096 threads[i].join(); 097 } 098 return threads; 099 } 100 101 static class LoggerAccessingThread extends Thread { 102 final CyclicBarrier barrier; 103 Logger logger; 104 int count; 105 106 LoggerAccessingThread(CyclicBarrier barrier, int count) { 107 this.barrier = barrier; 108 this.count = count; 109 } 110 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 129 public StringPrintStream(PrintStream ps) { 130 super(ps); 131 other = ps; 132 } 133 134 public void print(String s) { 135 other.print(s); 136 stringList.add(s); 137 } 138 139 public void println(String s) { 140 other.println(s); 141 stringList.add(s); 142 } 143 144 public void println(Object o) { 145 other.println(o); 146 stringList.add(o.toString()); 147 } 148 }; 149 150}