mirror of https://github.com/qos-ch/slf4j
fix SLF4J-469
This commit is contained in:
parent
ca93154c79
commit
c6c7a98a7e
|
|
@ -56,7 +56,12 @@
|
|||
<pathelement location="../slf4j-simple/target/slf4j-simple-${currentVersion}.jar" />
|
||||
</path >
|
||||
|
||||
<path id="pathNoBinding">
|
||||
<pathelement location="target/test-classes/" />
|
||||
<pathelement location="../slf4j-api/target/slf4j-api-${currentVersion}.jar" />
|
||||
</path >
|
||||
|
||||
|
||||
<path id="incompatibleMultiBinding">
|
||||
<pathelement location="target/test-classes/" />
|
||||
<pathelement location="../slf4j-api/target/slf4j-api-${currentVersion}.jar" />
|
||||
|
|
@ -102,11 +107,12 @@
|
|||
</target>
|
||||
|
||||
<target name="testAll" depends="init,
|
||||
testMissingSingletonMethod,
|
||||
testMissingSingletonMethod,
|
||||
testMismatch,
|
||||
testMatch,
|
||||
testMultiBinding,
|
||||
testIncompatibleMultiBinding,
|
||||
testNoBinding,
|
||||
testMatch,
|
||||
testMultiBinding,
|
||||
testIncompatibleMultiBinding,
|
||||
testFuture_16Series,
|
||||
testActiveSecurityManager">
|
||||
</target>
|
||||
|
|
@ -215,7 +221,17 @@
|
|||
</junit>
|
||||
|
||||
</target>
|
||||
|
||||
|
||||
<target name="testNoBinding">
|
||||
<junit printsummary="yes" fork="no" haltonfailure="yes">
|
||||
<classpath refid="pathNoBinding" />
|
||||
<formatter type="plain" />
|
||||
<test fork="yes" todir="target/unit-reports"
|
||||
outfile="TEST-NOBINDING"
|
||||
name="org.slf4j.helpers.NoBindingMultithreadedInitializationTest2" />
|
||||
</junit>
|
||||
</target>
|
||||
|
||||
|
||||
<condition property="runFromWithinIntegrationModule">
|
||||
<contains string="${user.dir}" substring="integration" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* Copyright (c) 2004-2016 QOS.ch
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
package org.slf4j.helpers;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class LoggerAccessingThread2 extends Thread {
|
||||
private static int LOOP_LEN = 64;
|
||||
|
||||
final CyclicBarrier barrier;
|
||||
final int count;
|
||||
final AtomicLong eventCount;
|
||||
List<Logger> loggerList;
|
||||
|
||||
public LoggerAccessingThread2(final CyclicBarrier barrier, List<Logger> loggerList, final int count, final AtomicLong eventCount) {
|
||||
this.barrier = barrier;
|
||||
this.loggerList = loggerList;
|
||||
this.count = count;
|
||||
this.eventCount = eventCount;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
barrier.await();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
String loggerNamePrefix = this.getClass().getName();
|
||||
for (int i = 0; i < LOOP_LEN; i++) {
|
||||
Logger logger = LoggerFactory.getLogger(loggerNamePrefix + "-" + count + "-" + i);
|
||||
loggerList.add(logger);
|
||||
Thread.yield();
|
||||
logger.info("in run method");
|
||||
eventCount.getAndIncrement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
/**
|
||||
* Copyright (c) 2004-2016 QOS.ch
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
package org.slf4j.helpers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.BrokenBarrierException;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.event.EventRecodingLogger;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class NoBindingMultithreadedInitializationTest2 extends TestCase {
|
||||
final protected static int THREAD_COUNT = 4 + Runtime.getRuntime().availableProcessors() * 2;
|
||||
|
||||
private final List<Logger> createdLoggers = Collections.synchronizedList(new ArrayList<Logger>());
|
||||
|
||||
protected final AtomicLong eventCount = new AtomicLong(0);
|
||||
final private CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
|
||||
|
||||
int diff = new Random().nextInt(10000);
|
||||
|
||||
|
||||
public NoBindingMultithreadedInitializationTest2(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public void testNoBindingMultiThreadedInitialization() throws InterruptedException, BrokenBarrierException {
|
||||
@SuppressWarnings("unused")
|
||||
LoggerAccessingThread2[] accessors = harness();
|
||||
|
||||
Logger logger = LoggerFactory.getLogger(getClass().getName());
|
||||
logger.info("hello");
|
||||
eventCount.getAndIncrement();
|
||||
|
||||
assertAllSubstLoggersAreFixed();
|
||||
long recordedEventCount = getRecordedEventCount();
|
||||
int LENIENCY_COUNT = 16;
|
||||
|
||||
long expectedEventCount = eventCount.get() + extraLogEvents();
|
||||
|
||||
assertTrue(expectedEventCount + " >= " + recordedEventCount, expectedEventCount >= recordedEventCount);
|
||||
assertTrue(expectedEventCount + " < " + recordedEventCount + "+" + LENIENCY_COUNT,
|
||||
expectedEventCount < recordedEventCount + LENIENCY_COUNT);
|
||||
}
|
||||
|
||||
protected int extraLogEvents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void assertAllSubstLoggersAreFixed() {
|
||||
for (Logger logger : createdLoggers) {
|
||||
if (logger instanceof SubstituteLogger) {
|
||||
SubstituteLogger substLogger = (SubstituteLogger) logger;
|
||||
if (substLogger.delegate() instanceof EventRecodingLogger)
|
||||
fail("substLogger " + substLogger.getName() + " has a delegate of type EventRecodingLogger");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private LoggerAccessingThread2[] harness() throws InterruptedException, BrokenBarrierException {
|
||||
LoggerAccessingThread2[] threads = new LoggerAccessingThread2[THREAD_COUNT];
|
||||
for (int i = 0; i < THREAD_COUNT; i++) {
|
||||
threads[i] = new LoggerAccessingThread2(barrier, createdLoggers, i, eventCount);
|
||||
threads[i].start();
|
||||
}
|
||||
|
||||
// trigger barrier
|
||||
barrier.await();
|
||||
|
||||
for (int i = 0; i < THREAD_COUNT; i++) {
|
||||
threads[i].join();
|
||||
}
|
||||
|
||||
return threads;
|
||||
}
|
||||
|
||||
final String loggerName = this.getClass().getName();
|
||||
|
||||
protected long getRecordedEventCount() {
|
||||
return eventCount.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -150,10 +150,6 @@ public final class LoggerFactory {
|
|||
StaticLoggerBinder.getSingleton();
|
||||
INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
|
||||
reportActualBinding(staticLoggerBinderPathSet);
|
||||
fixSubstituteLoggers();
|
||||
replayEvents();
|
||||
// release all resources in SUBST_FACTORY
|
||||
SUBST_FACTORY.clear();
|
||||
} catch (NoClassDefFoundError ncde) {
|
||||
String msg = ncde.getMessage();
|
||||
if (messageContainsOrgSlf4jImplStaticLoggerBinder(msg)) {
|
||||
|
|
@ -177,9 +173,18 @@ public final class LoggerFactory {
|
|||
} catch (Exception e) {
|
||||
failedBinding(e);
|
||||
throw new IllegalStateException("Unexpected initialization failure", e);
|
||||
} finally {
|
||||
postBindCleanUp();
|
||||
}
|
||||
}
|
||||
|
||||
private static void postBindCleanUp() {
|
||||
fixSubstituteLoggers();
|
||||
replayEvents();
|
||||
// release all resources in SUBST_FACTORY
|
||||
SUBST_FACTORY.clear();
|
||||
}
|
||||
|
||||
private static void fixSubstituteLoggers() {
|
||||
synchronized (SUBST_FACTORY) {
|
||||
SUBST_FACTORY.postInitialization();
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ abstract public class MultithreadedInitializationTest {
|
|||
|
||||
private final List<Logger> createdLoggers = Collections.synchronizedList(new ArrayList<Logger>());
|
||||
|
||||
final private AtomicLong eventCount = new AtomicLong(0);
|
||||
protected final AtomicLong eventCount = new AtomicLong(0);
|
||||
final private CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
|
||||
|
||||
int diff = new Random().nextInt(10000);
|
||||
|
|
|
|||
Loading…
Reference in New Issue