blob: d002946647cae31ffe41b14baf19d9f27755b997 [file] [log] [blame]
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.qpid.server.logging.logback;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.File;
import java.security.Principal;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.LogFileDetails;
import org.apache.qpid.server.logging.logback.VirtualHostFileLogger;
import org.apache.qpid.server.logging.logback.VirtualHostFileLoggerImpl;
import org.apache.qpid.server.model.BrokerTestHelper;
import org.apache.qpid.server.security.AccessControl;
import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.store.preferences.PreferenceStore;
import org.apache.qpid.util.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.configuration.updater.TaskExecutorImpl;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.BrokerModel;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.Model;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.SystemConfig;
import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.model.VirtualHostLogger;
import org.apache.qpid.server.model.VirtualHostNode;
import org.apache.qpid.server.virtualhost.TestMemoryVirtualHost;
import org.apache.qpid.test.utils.QpidTestCase;
public class VirtualHostLoggerTest extends QpidTestCase
{
private VirtualHost<?> _virtualHost;
private TaskExecutor _taskExecutor;
private File _baseFolder;
private File _logFile;
@Override
public void setUp() throws Exception
{
super.setUp();
_taskExecutor = new TaskExecutorImpl();
_taskExecutor.start();
Model model = BrokerModel.getInstance();
EventLogger eventLogger = mock(EventLogger.class);
SystemConfig<?> systemConfig = mock(SystemConfig.class);
when(systemConfig.getModel()).thenReturn(model);
when(systemConfig.getChildExecutor()).thenReturn(_taskExecutor);
when(systemConfig.getEventLogger()).thenReturn(eventLogger);
when(systemConfig.createPreferenceStore()).thenReturn(mock(PreferenceStore.class));
doReturn(SystemConfig.class).when(systemConfig).getCategoryClass();
Principal systemPrincipal = mock(Principal.class);
AccessControl accessControlMock = BrokerTestHelper.createAccessControlMock();
Broker broker = BrokerTestHelper.mockWithSystemPrincipalAndAccessControl(Broker.class, systemPrincipal,
accessControlMock);
when(broker.getModel()).thenReturn(model);
when(broker.getChildExecutor()).thenReturn(_taskExecutor);
when(broker.getParent(SystemConfig.class)).thenReturn(systemConfig);
doReturn(Broker.class).when(broker).getCategoryClass();
VirtualHostNode node = BrokerTestHelper.mockWithSystemPrincipalAndAccessControl(VirtualHostNode.class, systemPrincipal, accessControlMock);
when(node.getModel()).thenReturn(model);
when(node.getChildExecutor()).thenReturn(_taskExecutor);
when(node.getParent(Broker.class)).thenReturn(broker);
when(node.getConfigurationStore()).thenReturn(mock(DurableConfigurationStore.class));
doReturn(VirtualHostNode.class).when(node).getCategoryClass();
when(node.createPreferenceStore()).thenReturn(mock(PreferenceStore.class));
// use real VH object rather then mock in order to test create/start/stop functionality
Map<String, Object> attributes = new HashMap<>();
attributes.put(VirtualHost.NAME, getName());
attributes.put(VirtualHost.TYPE, TestMemoryVirtualHost.VIRTUAL_HOST_TYPE);
_virtualHost = new TestMemoryVirtualHost(attributes, node);
_virtualHost.open();
_baseFolder = new File(TMP_FOLDER, "test-sub-folder");
_logFile = new File(_baseFolder, "tmp-virtual-host.log." + System.currentTimeMillis());
if (_baseFolder.exists())
{
FileUtils.delete(_baseFolder, true);
}
}
@Override
public void tearDown() throws Exception
{
try
{
_virtualHost.close();
_taskExecutor.stopImmediately();
if (_baseFolder != null && _baseFolder.exists())
{
FileUtils.delete(_baseFolder, true);
}
}
finally
{
super.tearDown();
}
}
public void testAddLoggerWithDefaultSettings()
{
VirtualHostLogger logger = createVirtualHostLogger();
assertTrue("Unexpected logger created " + logger, logger instanceof VirtualHostFileLogger);
assertEquals("Unexpected log file", _logFile.getPath(), ((VirtualHostFileLogger<?>) logger).getFileName());
assertEquals("Unexpected state on creation", State.ACTIVE, logger.getState());
assertTrue("Log file does not exists", _logFile.exists());
Appender<ILoggingEvent> appender = ((ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME))
.getAppender(logger.getName());
assertTrue("Appender was not started", appender.isStarted());
}
public void testAddLoggerWithRollDailyOn()
{
VirtualHostLogger logger = createVirtualHostLogger(Collections.<String, Object>singletonMap("rollDaily", true));
assertTrue("Unexpected logger created " + logger, logger instanceof VirtualHostFileLogger);
assertEquals("Unexpected log file", _logFile.getPath(), ((VirtualHostFileLogger<?>) logger).getFileName());
assertEquals("Unexpected state on creation", State.ACTIVE, logger.getState());
assertTrue("Log file does not exists", _logFile.exists());
Appender<ILoggingEvent> appender = ((ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME))
.getAppender(logger.getName());
assertTrue("Appender was not started", appender.isStarted());
}
public void testDeleteLogger()
{
VirtualHostLogger logger = createVirtualHostLogger();
assertEquals("Unexpected state on creation", State.ACTIVE, logger.getState());
Appender<ILoggingEvent> appender = ((ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME))
.getAppender(logger.getName());
assertTrue("Appender is not started", appender.isStarted());
logger.delete();
appender = ((ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME)).getAppender(logger.getName());
assertNull("Appender should be detached on logger deletion", appender);
}
public void testLoggersRemovedOnVirtualHostStop()
{
VirtualHostLogger logger = createVirtualHostLogger();
_virtualHost.stop();
Appender<ILoggingEvent> appender = ((ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME))
.getAppender(logger.getName());
assertNull("Appender was not deleted", appender);
}
public void testLoggersRemovedOnVirtualHostClose()
{
VirtualHostLogger logger = createVirtualHostLogger();
_virtualHost.close();
Appender<ILoggingEvent> appender = ((ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME))
.getAppender(logger.getName());
assertNull("Appender was not deleted", appender);
}
public void testGetLogFiles()
{
VirtualHostFileLogger logger = (VirtualHostFileLogger)createVirtualHostLogger();
Collection<LogFileDetails> logFileDetails = logger.getLogFiles();
assertEquals("File details should not be empty", 1, logFileDetails.size());
for(LogFileDetails logFile : logFileDetails)
{
assertEquals("Unexpected log name", _logFile.getName(), logFile.getName());
assertEquals("Unexpected log name", 0, logFile.getSize());
assertEquals("Unexpected log name", _logFile.lastModified(), logFile.getLastModified());
}
}
public void testGetLogFilesOnResolutionErrors()
{
VirtualHostFileLogger logger = createErrorredLogger();
Collection<LogFileDetails> logFileDetails = logger.getLogFiles();
assertTrue("File details should be empty", logFileDetails.isEmpty());
}
public void testStopLoggingLoggerInErroredState()
{
VirtualHostFileLogger logger = createErrorredLogger();
logger.stopLogging();
}
private VirtualHostFileLogger createErrorredLogger()
{
Map<String, Object> attributes = new HashMap<>();
attributes.put(VirtualHostLogger.NAME, getTestName());
attributes.put(ConfiguredObject.TYPE, VirtualHostFileLogger.TYPE);
attributes.put(VirtualHostFileLogger.FILE_NAME, _logFile.getPath());
attributes.put(VirtualHostFileLogger.MAX_FILE_SIZE, "invalid");
VirtualHostFileLogger logger = new VirtualHostFileLoggerImpl(attributes, _virtualHost);
logger.open();
assertEquals("Unexpected state", State.ERRORED, logger.getState());
return logger;
}
private VirtualHostLogger createVirtualHostLogger()
{
return createVirtualHostLogger(Collections.<String,Object>emptyMap());
}
private VirtualHostLogger createVirtualHostLogger(Map<String, Object> additionalAttributes)
{
Map<String, Object> attributes = new HashMap<>(additionalAttributes);
attributes.put(VirtualHostLogger.NAME, getTestName());
attributes.put(ConfiguredObject.TYPE, VirtualHostFileLogger.TYPE);
attributes.put(VirtualHostFileLogger.FILE_NAME, _logFile.getPath());
return _virtualHost.createChild(VirtualHostLogger.class, attributes);
}
}