/* * Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.hazelcast.logging; import com.hazelcast.test.HazelcastSerialClassRunner; import com.hazelcast.test.HazelcastTestSupport; import com.hazelcast.test.annotation.NightlyTest; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import java.lang.reflect.Field; import static com.hazelcast.spi.properties.GroupProperty.LOGGING_TYPE; import static java.util.concurrent.TimeUnit.SECONDS; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.withSettings; @RunWith(HazelcastSerialClassRunner.class) @Category(NightlyTest.class) public class LoggerStressTest extends HazelcastTestSupport { private static final int TEST_DURATION_SECONDS = 5; private static final int THREAD_COUNT = 4; private static final String LOGGING_CLASS_PROP_NAME = "hazelcast.logging.class"; private String originalLoggingClass; private String originalLoggingType; private LoggerFactory originLoggerFactory; @Before public void setUp() throws Exception { originalLoggingClass = System.getProperty(LOGGING_CLASS_PROP_NAME); originalLoggingType = System.getProperty(LOGGING_TYPE.getName()); originLoggerFactory = (LoggerFactory) getLoggerFactoryField().get(null); } @After public void tearDown() throws Exception { restoreProperty(LOGGING_CLASS_PROP_NAME, originalLoggingClass); restoreProperty(LOGGING_TYPE.getName(), originalLoggingType); getLoggerFactoryField().set(null, originLoggerFactory); } @Test public void stressThreadsWithCustomLoggingClass() throws Exception { System.setProperty(LOGGING_CLASS_PROP_NAME, LoggingFactoryStub.class.getName()); long deadLine = System.currentTimeMillis() + SECONDS.toMillis(TEST_DURATION_SECONDS); StressThread[] threads = startStressThreads(deadLine); assertThreadsEventuallyFinishesWithoutException(threads); } @Test public void stressThreadsWithLoggingType() throws Exception { System.setProperty(LOGGING_TYPE.getName(), "log4j"); long deadLine = System.currentTimeMillis() + SECONDS.toMillis(TEST_DURATION_SECONDS); StressThread[] threads = startStressThreads(deadLine); assertThreadsEventuallyFinishesWithoutException(threads); } private static Field getLoggerFactoryField() { Field loggerFactoryField; try { loggerFactoryField = Logger.class.getDeclaredField("loggerFactory"); } catch (NoSuchFieldException e) { throw new AssertionError("LoggerFactory field not found"); } loggerFactoryField.setAccessible(true); return loggerFactoryField; } private static void restoreProperty(String name, String value) { if (value == null) { System.clearProperty(name); } else { System.setProperty(name, value); } } private static StressThread[] startStressThreads(long deadLine) { StressThread[] threads = new StressThread[THREAD_COUNT]; for (int i = 0; i < THREAD_COUNT; i++) { threads[i] = new StressThread(deadLine); } for (int i = 0; i < THREAD_COUNT; i++) { threads[i].start(); } return threads; } private static void assertThreadsEventuallyFinishesWithoutException(StressThread[] threads) throws Exception { for (StressThread thread : threads) { thread.join(); Exception exception = thread.e; if (exception != null) { throw exception; } } } private static class LoggingFactoryStub implements LoggerFactory { @Override public ILogger getLogger(String name) { return mock(ILogger.class, withSettings().stubOnly()); } } private static class StressThread extends Thread { private final long deadLine; private Exception e; StressThread(long deadLine) { this.deadLine = deadLine; } @Override public void run() { try { while (System.currentTimeMillis() < deadLine) { Logger.getLogger(randomName()); } } catch (Exception e) { this.e = e; } } } }