/*
* ALMA - Atacama Large Millimiter Array
* (c) European Southern Observatory, 2002
* Copyright by ESO (in the framework of the ALMA collaboration),
* All rights reserved
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
package alma.contLogTest.TestLogLevelsCompImpl;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import junit.framework.Assert;
import junit.framework.TestCase;
import alma.ACSErrTypeCommon.CouldntPerformActionEx;
import alma.ACSErrTypeCommon.wrappers.AcsJCouldntPerformActionEx;
import alma.Logging.LoggingConfigurable;
import alma.acs.component.client.ComponentClientTestCase;
import alma.acs.logging.engine.LogReceiver;
import alma.acs.logging.level.AcsLogLevelDefinition;
import alma.contLogTest.TestLogLevelsComp;
/**
* Requires Java component "TESTLOG1" of type <code>alma.contLogTest.TestLogLevelsComp</code> to be available.
*
* @author eallaert 30 October 2007
*/
public class TestLogLevelsCompTest extends ComponentClientTestCase
{
public static final String PROPERTYNAME_COMPONENTNAMES = "TEST_COMP_NAMES";
private Set<String> componentNames = new LinkedHashSet<String>();
private List<TestLogLevelsComp> components;
private ContainerTestUtil containerTestUtil;
/**
* @throws java.lang.Exception
*/
public TestLogLevelsCompTest() throws Exception
{
super(TestLogLevelsCompTest.class.getSimpleName());
}
/**
* @see TestCase#setUp()
*/
protected void setUp() throws Exception {
super.setUp();
// set names of test components, if not done already in the main method
String compNames = System.getProperty(PROPERTYNAME_COMPONENTNAMES);
if (compNames != null) {
StringTokenizer tok = new StringTokenizer(compNames);
while (tok.hasMoreTokens()) {
componentNames.add(tok.nextToken());
}
}
components = new ArrayList<TestLogLevelsComp>();
for (String compName : componentNames) {
components.add(alma.contLogTest.TestLogLevelsCompHelper.narrow(getContainerServices().getComponent(compName)));
}
containerTestUtil = new ContainerTestUtil(getContainerServices(), m_acsManagerProxy);
containerTestUtil.loginToManager();
}
/**
* @see TestCase#tearDown()
*/
protected void tearDown() throws Exception {
for (String compName : componentNames) {
//System.out.println("tearDown - about to release "+ compName);
getContainerServices().releaseComponent(compName);
}
//System.out.println("tearDown - about to log-out from Manager");
containerTestUtil.logoutFromManager();
//System.out.println("tearDown - about to tearDown() superClass");
super.tearDown();
//System.out.println("tearDown - done with tearDown() of superClass");
}
/**
* @throws Exception
*/
public void testGetLevels() throws Exception
{
int[] levels;
for (TestLogLevelsComp testlogComp : components) {
try {
levels = testlogComp.getLevels();
} catch (CouldntPerformActionEx ex) {
throw AcsJCouldntPerformActionEx.fromCouldntPerformActionEx(ex);
}
String componentName = testlogComp.name();
// Prepare the log levels via the container's LoggingConfigurable interface
String containerName = containerTestUtil.resolveContainerName(componentName);
LoggingConfigurable containerLogConfig = containerTestUtil.getContainerLoggingIF(containerName);
// @TODO get logger name from the container via a new IDL method, because the logger name
// may not be the same as the container (e.g. for C++ containers).
//String loggerName = containerName;
String loggerName = componentName;
// Get the log level that our test component is subject to
alma.Logging.LoggingConfigurablePackage.LogLevels componentLogLevels = containerLogConfig.get_logLevels(loggerName);
if (componentLogLevels.useDefault) {
m_logger.info("levels from component's getLevels method (hardcoded remote, local, effective): "
+ levels[0] + ", " + levels[1] + ", " + levels[2] + ", " + levels[3] + ", " + levels[4]);
Assert.assertEquals(levels[3], componentLogLevels.minLogLevel);
Assert.assertEquals(levels[4], componentLogLevels.minLogLevelLocal);
}
else {
m_logger.info("levels from component's getLevels method and LoggingConfigurable: "
+ levels[0] + ", " + levels[1] + ", " + levels[2] + ", " + levels[3] + ", " + levels[4]);
}
// levels[0-4]: hardcoded remote, hardcoded local, AcsLogger, AcsLogHandler, StdoutConsoleHandler
Assert.assertTrue(levels[3] != -1);
Assert.assertTrue(levels[4] != -1);
// The AcsLogger setting should be the minimum of the one for AcsLogHandler and StdoutConsoleHandler
int minLevel = levels[3];
if (levels[3] > levels[4] || levels[3] == -1)
minLevel = levels[4];
Assert.assertEquals(levels[2], minLevel);
}
// // Sleep is to work-around a race condition, whereby the tearDown() can get called "too early"
// // (logging not properly initialised when it is already stopped after running this short method).
// Thread.sleep(3000);
}
/**
* This test uses the LoggingConfigurable interface implemented by all containers to set log levels
* These log levels are then expected to be independent of the initial CDB settings, according to precedence rules.
* The test verifies that the levels are applied correctly by commanding the test components to log messages
* at various log levels. The test listens on the Log service to compare the messages actually sent
* with what is expected for the current log level settings.
*/
public void testLoggingConfigurableCentralLogLevels() throws Exception {
LogSeriesExpectant expectant = new LogSeriesExpectant(getLogReceiver());
// All log levels, including OFF
int[] centralLogLevels;
// Excluding OFF
int[] sendLogLevels;
// Only with OFF
int[] offLogLevels;
centralLogLevels = new int[AcsLogLevelDefinition.values().length];
sendLogLevels = new int[AcsLogLevelDefinition.values().length - 1];
offLogLevels = new int[1];
int i = 0;
int maxLogLevel = -1;
// We will rely here on the fact that AcsLogLevelDefinition has the
// log levels ordered, with OFF being the last one.
for (AcsLogLevelDefinition lld : AcsLogLevelDefinition.values()) {
if (lld.name.equalsIgnoreCase("OFF")) {
offLogLevels[0] = lld.value;
}
else {
maxLogLevel = Math.max(maxLogLevel, lld.value);
sendLogLevels[i] = lld.value;
}
centralLogLevels[i++] = lld.value;
}
int waitTimeSeconds = 4;
for (TestLogLevelsComp testComp : components) {
String componentName = testComp.name();
// Prepare the log levels via the container's LoggingConfigurable interface
String containerName = containerTestUtil.resolveContainerName(componentName);
LoggingConfigurable containerLogConfig = containerTestUtil.getContainerLoggingIF(containerName);
// @TODO get logger name from the component via a new IDL method, because the logger name
// may not be the same as the component name (e.g. for C++ components).
String loggerName = componentName;
// Set the log level that our test component is subject to (either default level or individual level depending on CDB config)
alma.Logging.LoggingConfigurablePackage.LogLevels componentLogLevels = containerLogConfig.get_logLevels(loggerName);
for (int level : centralLogLevels) {
// The min log level we set for the component and test its log output against.
short minLogLevelCentral = (short)level;
componentLogLevels.minLogLevel = minLogLevelCentral;
if (componentLogLevels.useDefault) {
// @TODO: add a test as well to change the specific level, and then verify
// if useDefault becomes false.
containerLogConfig.set_default_logLevels(componentLogLevels);
m_logger.info("Set default log level for container " + containerName + " to " + minLogLevelCentral + " to be used by component " + componentName);
}
else {
// @TODO: add a test to change the default level, and see if it impacts specific logger
containerLogConfig.set_logLevels(loggerName, componentLogLevels);
m_logger.info("Set individual log level for component " + componentName + " (running in container " + containerName + ") to " + minLogLevelCentral);
}
expectant.clearLogs();
m_logger.info("Will call 'logDummyMessages' on component " + componentName);
testComp.logDummyMessages(sendLogLevels);
//testComp.logDummyMessages(centralLogLevels);
m_logger.info("Will wait " + waitTimeSeconds + " seconds to receive (some of) these log messages.");
LogSeriesExpectant.LogList logRecordsReceived = expectant.awaitLogRecords(loggerName, waitTimeSeconds);
System.out.println("Got " + logRecordsReceived.size() + " records from logger " + loggerName);
for (LogReceiver.ReceivedLogRecord logRecord : logRecordsReceived) {
System.out.println("(level=" + logRecord.getLevel().acsCoreLevel.value + ") " + logRecord.getMessage());
}
if (minLogLevelCentral > maxLogLevel) {
// minLogLevelCentral must be set to OFF - no logs should get through
assertEquals(0, logRecordsReceived.size());
}
else {
// The next assertion will fail here if there were no logs received,
// as getMinLogLevel will return then the value 2147483647 (-1).
assertEquals(minLogLevelCentral, logRecordsReceived.getMinLogLevel());
assertEquals(maxLogLevel, logRecordsReceived.getMaxLogLevel());
}
// logging a msg at level OFF should lead to an exception, independent from central level
try {
testComp.logDummyMessages(offLogLevels);
// C++ containers don't seem to be able to throw exception in this case
m_logger.info("Sending a log with level OFF did not throw exception.");
// Consume the log that says it is the last log message, unless the current level is OFF
if (minLogLevelCentral <= maxLogLevel) {
logRecordsReceived = expectant.awaitLogRecords(loggerName, waitTimeSeconds);
assertEquals(1, logRecordsReceived.size());
}
}
catch (org.omg.CORBA.UNKNOWN ex) {
if (ex.getLocalizedMessage().startsWith("Server-side Exception: java.lang.IllegalArgumentException")) {
// Obviously the case for Java
System.out.println("Got illegal argument exception for attempting to send log with level OFF, as expected.");
}
else if (ex.getLocalizedMessage().startsWith("Server-side Exception: null")) {
// This is what Python does
System.out.println("Got exception for attempting to send log with level OFF, as expected.");
}
else {
// The exception we got is not the one expected
throw ex;
}
}
//System.out.println("Finished testing level " + level);
}
//System.out.println("Finished testing component " + componentName);
}
//System.out.println("Finished testing all components - done with testLoggingConfigurableCentralLogLevels()");
}
public static void main(String[] args)
{
alma.acs.testsupport.tat.NoDotJUnitRunner.run(TestLogLevelsCompTest.class);
}
}