/*
* Copyright (c) 2010-2015 Evolveum
*
* 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.evolveum.midpoint.model.intest;
import static org.testng.AssertJUnit.assertTrue;
import static com.evolveum.midpoint.test.IntegrationTestTools.*;
import java.util.Collection;
import com.evolveum.midpoint.util.aspect.ProfilingDataManager;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;
import org.springframework.test.context.ContextConfiguration;
import org.testng.annotations.Test;
import com.evolveum.icf.dummy.connector.DummyConnector;
import com.evolveum.midpoint.common.LoggingConfigurationManager;
import com.evolveum.midpoint.model.api.ModelExecuteOptions;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismObjectDefinition;
import com.evolveum.midpoint.prism.delta.ItemDelta;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.delta.PropertyDelta;
import com.evolveum.midpoint.prism.util.PrismTestUtil;
import com.evolveum.midpoint.schema.internals.InternalsConfig;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.MiscSchemaUtil;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.test.IntegrationTestTools;
import com.evolveum.midpoint.test.util.LogfileTestTailer;
import com.evolveum.midpoint.test.util.TestUtil;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AuditingConfigurationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ClassLoggerConfigurationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.LoggingComponentType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.LoggingConfigurationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.LoggingLevelType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.SubSystemLoggerConfigurationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemObjectsType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;
/**
* @author semancik
*
*/
@ContextConfiguration(locations = {"classpath:ctx-model-intest-test-main.xml"})
@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
public class TestLoggingConfiguration extends AbstractConfiguredModelIntegrationTest {
final String JUL_LOGGER_NAME = "com.exmple.jul.logger";
@Override
public void initSystem(Task initTask, OperationResult initResult) throws Exception {
InternalsConfig.avoidLoggingChange = false;
// DO NOT call super.initSystem() as this will install system config. We do not want that here.
userAdministrator = repoAddObjectFromFile(USER_ADMINISTRATOR_FILE, initResult);
repoAddObjectFromFile(ROLE_SUPERUSER_FILE, initResult);
login(userAdministrator);
}
@Test
public void test001CreateSystemConfiguration() throws Exception {
final String TEST_NAME = "test001CreateSystemConfiguration";
TestUtil.displayTestTile(TEST_NAME);
// GIVEN
LogfileTestTailer tailer = new LogfileTestTailer(LoggingConfigurationManager.AUDIT_LOGGER_NAME);
PrismObject<SystemConfigurationType> systemConfiguration = PrismTestUtil.parseObject(SYSTEM_CONFIGURATION_FILE);
Task task = taskManager.createTaskInstance(TestLoggingConfiguration.class.getName()+"."+TEST_NAME);
OperationResult result = task.getResult();
ObjectDelta<SystemConfigurationType> systemConfigurationAddDelta = ObjectDelta.createAddDelta(systemConfiguration);
Collection<ObjectDelta<? extends ObjectType>> deltas = MiscSchemaUtil.createCollection(systemConfigurationAddDelta);
// WHEN
modelService.executeChanges(deltas, null, task, result);
// THEN
tailer.logAndTail();
assertBasicLogging(tailer);
// TODO: more asserts
tailer.close();
}
@Test
public void test002InitialConfiguration() throws Exception {
final String TEST_NAME = "test002InitialConfiguration";
TestUtil.displayTestTile(TEST_NAME);
// GIVEN
LogfileTestTailer tailer = new LogfileTestTailer(LoggingConfigurationManager.AUDIT_LOGGER_NAME);
Task task = taskManager.createTaskInstance(TestLoggingConfiguration.class.getName()+"."+TEST_NAME);
OperationResult result = task.getResult();
PrismObject<SystemConfigurationType> systemConfiguration = PrismTestUtil.parseObject(SYSTEM_CONFIGURATION_FILE);
LoggingConfigurationType logging = systemConfiguration.asObjectable().getLogging();
applyTestLoggingConfig(logging);
SubSystemLoggerConfigurationType modelSubSystemLogger = new SubSystemLoggerConfigurationType();
modelSubSystemLogger.setComponent(LoggingComponentType.PROVISIONING);
modelSubSystemLogger.setLevel(LoggingLevelType.TRACE);
logging.getSubSystemLogger().add(modelSubSystemLogger);
PrismObjectDefinition<SystemConfigurationType> systemConfigurationTypeDefinition =
prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(SystemConfigurationType.class);
Collection<? extends ItemDelta> modifications =
PropertyDelta.createModificationReplacePropertyCollection(SystemConfigurationType.F_LOGGING,
systemConfigurationTypeDefinition, logging);
// Modify directly in repository, so the logging code in model will not notice the change
repositoryService.modifyObject(SystemConfigurationType.class, AbstractInitializedModelIntegrationTest.SYSTEM_CONFIGURATION_OID,
modifications, result);
// precondition
tailer.logAndTail();
assertBasicLogging(tailer);
tailer.assertMarkerNotLogged(LogfileTestTailer.LEVEL_TRACE, ProfilingDataManager.Subsystem.PROVISIONING.name());
// WHEN
repositoryService.postInit(result);
modelService.postInit(result);
// THEN
tailer.logAndTail();
assertBasicLogging(tailer);
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_TRACE, ProfilingDataManager.Subsystem.PROVISIONING.name());
tailer.close();
}
/**
* Overwrite initial system configuration by itself. Check that everything
* still works.
*/
@Test
public void test004OverwriteInitialConfiguration() throws Exception {
final String TEST_NAME = "test004OverwriteInitialConfiguration";
TestUtil.displayTestTile(TEST_NAME);
// GIVEN
LogfileTestTailer tailer = new LogfileTestTailer(LoggingConfigurationManager.AUDIT_LOGGER_NAME);
Task task = taskManager.createTaskInstance(TestLoggingConfiguration.class.getName()+"."+TEST_NAME);
OperationResult result = task.getResult();
PrismObject<SystemConfigurationType> systemConfiguration = getObject(SystemConfigurationType.class, SystemObjectsType.SYSTEM_CONFIGURATION.value());
String previousVersion = systemConfiguration.getVersion();
systemConfiguration.setVersion(null);
// precondition
tailer.logAndTail();
assertBasicLogging(tailer);
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_TRACE, ProfilingDataManager.Subsystem.PROVISIONING.name());
ObjectDelta<SystemConfigurationType> delta = ObjectDelta.createAddDelta(systemConfiguration);
ModelExecuteOptions options = ModelExecuteOptions.createOverwrite();
// WHEN
modelService.executeChanges(MiscSchemaUtil.createCollection(delta), options, task, result);
// THEN
result.computeStatus();
TestUtil.assertSuccess(result);
tailer.logAndTail();
assertBasicLogging(tailer);
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_TRACE, ProfilingDataManager.Subsystem.PROVISIONING.name());
tailer.close();
PrismObject<SystemConfigurationType> systemConfigurationNew = getObject(SystemConfigurationType.class, SystemObjectsType.SYSTEM_CONFIGURATION.value());
String newVersion = systemConfigurationNew.getVersion();
assertTrue("Versions do not follow: "+previousVersion+" -> "+newVersion,
Integer.parseInt(previousVersion) < Integer.parseInt(newVersion));
}
@Test
public void test010AddModelSubsystemLogger() throws Exception {
final String TEST_NAME = "test010AddModelSubsystemLogger";
TestUtil.displayTestTile(TEST_NAME);
// GIVEN
LogfileTestTailer tailer = new LogfileTestTailer(LoggingConfigurationManager.AUDIT_LOGGER_NAME);
Task task = taskManager.createTaskInstance(TestLoggingConfiguration.class.getName()+"."+TEST_NAME);
OperationResult result = task.getResult();
// Precondition
tailer.logAndTail();
assertBasicLogging(tailer);
tailer.assertMarkerNotLogged(LogfileTestTailer.LEVEL_DEBUG, ProfilingDataManager.Subsystem.MODEL.name());
tailer.assertMarkerNotLogged(LogfileTestTailer.LEVEL_TRACE, ProfilingDataManager.Subsystem.MODEL.name());
// Setup
PrismObject<SystemConfigurationType> systemConfiguration =
PrismTestUtil.parseObject(AbstractInitializedModelIntegrationTest.SYSTEM_CONFIGURATION_FILE);
LoggingConfigurationType logging = systemConfiguration.asObjectable().getLogging();
applyTestLoggingConfig(logging);
SubSystemLoggerConfigurationType modelSubSystemLogger = new SubSystemLoggerConfigurationType();
modelSubSystemLogger.setComponent(LoggingComponentType.MODEL);
modelSubSystemLogger.setLevel(LoggingLevelType.DEBUG);
logging.getSubSystemLogger().add(modelSubSystemLogger);
ObjectDelta<SystemConfigurationType> systemConfigDelta = ObjectDelta.createModificationReplaceProperty(SystemConfigurationType.class,
AbstractInitializedModelIntegrationTest.SYSTEM_CONFIGURATION_OID, SystemConfigurationType.F_LOGGING, prismContext,
logging);
Collection<ObjectDelta<? extends ObjectType>> deltas = MiscSchemaUtil.createCollection(systemConfigDelta);
// WHEN
modelService.executeChanges(deltas, null, task, result);
// THEN
tailer.logAndTail();
assertBasicLogging(tailer);
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_DEBUG, ProfilingDataManager.Subsystem.MODEL.name());
tailer.assertMarkerNotLogged(LogfileTestTailer.LEVEL_TRACE, ProfilingDataManager.Subsystem.MODEL.name());
// Test that the class logger for this test messages works
// GIVEN
tailer.setExpecteMessage("This is THE MESSage");
// WHEN
display("This is THE MESSage");
// THEN
tailer.tail();
tailer.assertExpectedMessage();
tailer.close();
}
@Test
public void test020JulLoggingDisabled() throws Exception {
final String TEST_NAME = "test020JulLoggingDisabled";
TestUtil.displayTestTile(TEST_NAME);
// GIVEN
LogfileTestTailer tailer = new LogfileTestTailer(LoggingConfigurationManager.AUDIT_LOGGER_NAME);
java.util.logging.Logger julLogger = java.util.logging.Logger.getLogger(JUL_LOGGER_NAME);
// WHEN
julLogger.severe(LogfileTestTailer.MARKER + " JULsevere");
julLogger.warning(LogfileTestTailer.MARKER + " JULwarning");
julLogger.info(LogfileTestTailer.MARKER + " JULinfo");
julLogger.fine(LogfileTestTailer.MARKER + " JULfine");
julLogger.finer(LogfileTestTailer.MARKER + " JULfiner");
julLogger.finest(LogfileTestTailer.MARKER + " JULfinest");
tailer.tail();
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_ERROR, "JULsevere");
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_WARN, "JULwarning");
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_INFO, "JULinfo");
tailer.assertMarkerNotLogged(LogfileTestTailer.LEVEL_DEBUG, "JULfine");
tailer.assertMarkerNotLogged(LogfileTestTailer.LEVEL_DEBUG, "JULfiner");
tailer.assertMarkerNotLogged(LogfileTestTailer.LEVEL_TRACE, "JULfinest");
tailer.close();
}
@Test
public void test021JulLoggingEnabled() throws Exception {
final String TEST_NAME = "test021JulLoggingEnabled";
TestUtil.displayTestTile(TEST_NAME);
// GIVEN
LogfileTestTailer tailer = new LogfileTestTailer(LoggingConfigurationManager.AUDIT_LOGGER_NAME);
java.util.logging.Logger julLogger = java.util.logging.Logger.getLogger(JUL_LOGGER_NAME);
Task task = taskManager.createTaskInstance(TestLoggingConfiguration.class.getName()+"."+TEST_NAME);
OperationResult result = task.getResult();
// Setup
PrismObject<SystemConfigurationType> systemConfiguration =
PrismTestUtil.parseObject(AbstractInitializedModelIntegrationTest.SYSTEM_CONFIGURATION_FILE);
LoggingConfigurationType logging = systemConfiguration.asObjectable().getLogging();
applyTestLoggingConfig(logging);
ClassLoggerConfigurationType classLogerCongif = new ClassLoggerConfigurationType();
classLogerCongif.setPackage(JUL_LOGGER_NAME);
classLogerCongif.setLevel(LoggingLevelType.ALL);
logging.getClassLogger().add(classLogerCongif );
ObjectDelta<SystemConfigurationType> systemConfigDelta = ObjectDelta.createModificationReplaceProperty(SystemConfigurationType.class,
AbstractInitializedModelIntegrationTest.SYSTEM_CONFIGURATION_OID, SystemConfigurationType.F_LOGGING, prismContext,
logging);
Collection<ObjectDelta<? extends ObjectType>> deltas = MiscSchemaUtil.createCollection(systemConfigDelta);
modelService.executeChanges(deltas, null, task, result);
// WHEN
julLogger.severe(LogfileTestTailer.MARKER + " JULsevere");
julLogger.warning(LogfileTestTailer.MARKER + " JULwarning");
julLogger.info(LogfileTestTailer.MARKER + " JULinfo");
julLogger.fine(LogfileTestTailer.MARKER + " JULfine");
julLogger.finer(LogfileTestTailer.MARKER + " JULfiner");
julLogger.finest(LogfileTestTailer.MARKER + " JULfinest");
tailer.tail();
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_ERROR, "JULsevere");
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_WARN, "JULwarning");
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_INFO, "JULinfo");
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_DEBUG, "JULfine");
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_DEBUG, "JULfiner");
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_TRACE, "JULfinest");
tailer.close();
}
/**
* Test if connectors log properly. The dummy connector logs on all levels when the
* "test" operation is invoked. So let's try it.
*/
@Test
public void test030ConnectorLogging() throws Exception {
final String TEST_NAME = "test030ConnectorLogging";
TestUtil.displayTestTile(TEST_NAME);
// GIVEN
LogfileTestTailer tailer = new LogfileTestTailer(LoggingConfigurationManager.AUDIT_LOGGER_NAME);
// ICF logging is prefixing the messages;
tailer.setAllowPrefix(true);
Task task = taskManager.createTaskInstance(TestLoggingConfiguration.class.getName()+"."+TEST_NAME);
OperationResult result = task.getResult();
importObjectFromFile(RESOURCE_DUMMY_FILE, result);
// Setup
PrismObject<SystemConfigurationType> systemConfiguration =
PrismTestUtil.parseObject(AbstractInitializedModelIntegrationTest.SYSTEM_CONFIGURATION_FILE);
LoggingConfigurationType logging = systemConfiguration.asObjectable().getLogging();
applyTestLoggingConfig(logging);
ClassLoggerConfigurationType classLogerCongif = new ClassLoggerConfigurationType();
classLogerCongif.setPackage(DummyConnector.class.getPackage().getName());
classLogerCongif.setLevel(LoggingLevelType.ALL);
logging.getClassLogger().add(classLogerCongif );
ObjectDelta<SystemConfigurationType> systemConfigDelta = ObjectDelta.createModificationReplaceProperty(SystemConfigurationType.class,
AbstractInitializedModelIntegrationTest.SYSTEM_CONFIGURATION_OID, SystemConfigurationType.F_LOGGING, prismContext,
logging);
Collection<ObjectDelta<? extends ObjectType>> deltas = MiscSchemaUtil.createCollection(systemConfigDelta);
modelService.executeChanges(deltas, null, task, result);
// INFO part
java.util.logging.Logger dummyConnctorJulLogger = java.util.logging.Logger.getLogger(DummyConnector.class.getName());
LOGGER.info("Dummy connector JUL logger as seen by the test: {}; classloader {}",
dummyConnctorJulLogger, dummyConnctorJulLogger.getClass().getClassLoader());
// WHEN
modelService.testResource(RESOURCE_DUMMY_OID, task);
// THEN
tailer.tail();
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_ERROR, "DummyConnectorIcfError");
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_WARN, "DummyConnectorIcfWarn");
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_DEBUG, "DummyConnectorIcfInfo");
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_TRACE, "DummyConnectorIcfOk");
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_ERROR, "DummyConnectorJULsevere");
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_WARN, "DummyConnectorJULwarning");
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_INFO, "DummyConnectorJULinfo");
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_DEBUG, "DummyConnectorJULfine");
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_DEBUG, "DummyConnectorJULfiner");
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_TRACE, "DummyConnectorJULfinest");
tailer.close();
}
@Test
public void test101EnableBasicAudit() throws Exception {
TestUtil.displayTestTile("test101EnableBasicAudit");
// GIVEN
LogfileTestTailer tailer = new LogfileTestTailer(LoggingConfigurationManager.AUDIT_LOGGER_NAME);
Task task = taskManager.createTaskInstance(TestLoggingConfiguration.class.getName()+".test101EnableBasicAudit");
OperationResult result = task.getResult();
// Precondition
tailer.tail();
tailer.assertNoAudit();
// Setup
PrismObject<SystemConfigurationType> systemConfiguration =
PrismTestUtil.parseObject(AbstractInitializedModelIntegrationTest.SYSTEM_CONFIGURATION_FILE);
LoggingConfigurationType logging = systemConfiguration.asObjectable().getLogging();
applyTestLoggingConfig(logging);
AuditingConfigurationType auditingConfigurationType = logging.getAuditing();
if (auditingConfigurationType == null) {
auditingConfigurationType = new AuditingConfigurationType();
logging.setAuditing(auditingConfigurationType);
}
auditingConfigurationType.setEnabled(true);
auditingConfigurationType.setDetails(false);
ObjectDelta<SystemConfigurationType> systemConfigDelta = ObjectDelta.createModificationReplaceProperty(SystemConfigurationType.class,
AbstractInitializedModelIntegrationTest.SYSTEM_CONFIGURATION_OID, SystemConfigurationType.F_LOGGING, prismContext,
logging);
Collection<ObjectDelta<? extends ObjectType>> deltas = MiscSchemaUtil.createCollection(systemConfigDelta);
// WHEN
modelService.executeChanges(deltas, null, task, result);
// Make sure that the (optional) audit message from the above change will not get into the way
tailer.tail();
tailer.reset();
// This message will appear in the log and will help diagnose problems
display("TEST: Applied audit config, going to execute test change");
// try do execute some change (add user object), it should be audited
PrismObject<UserType> user = PrismTestUtil.parseObject(AbstractInitializedModelIntegrationTest.USER_JACK_FILE);
deltas = MiscSchemaUtil.createCollection(ObjectDelta.createAddDelta(user));
modelService.executeChanges(deltas, null, task, result);
// This message will appear in the log and will help diagnose problems
display("TEST: Executed test change");
// THEN
tailer.tail();
tailer.assertAudit(2);
tailer.assertAuditRequest();
tailer.assertAuditExecution();
tailer.close();
}
private void applyTestLoggingConfig(LoggingConfigurationType logging) {
// Make sure that this class has a special entry in the config so we will see the messages from this test code
ClassLoggerConfigurationType testClassLogger = new ClassLoggerConfigurationType();
testClassLogger.setPackage(TestLoggingConfiguration.class.getName());
testClassLogger.setLevel(LoggingLevelType.TRACE);
logging.getClassLogger().add(testClassLogger);
ClassLoggerConfigurationType integrationTestToolsLogger = new ClassLoggerConfigurationType();
integrationTestToolsLogger.setPackage(IntegrationTestTools.class.getName());
integrationTestToolsLogger.setLevel(LoggingLevelType.TRACE);
logging.getClassLogger().add(integrationTestToolsLogger);
}
private void assertBasicLogging(LogfileTestTailer tailer) {
tailer.assertMarkerLogged(LogfileTestTailer.LEVEL_ERROR, ProfilingDataManager.Subsystem.MODEL.name());
tailer.assertMarkerNotLogged(LogfileTestTailer.LEVEL_TRACE, ProfilingDataManager.Subsystem.REPOSITORY.name());
}
}