/*
* ALMA - Atacama Large Millimiter Array
* (c) European Southern Observatory, 2002
* Copyright by ESO (in the framework of the ALMA collaboration)
* and Cosylab 2002, 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.acs.jlog.test;
import java.text.FieldPosition;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Vector;
import alma.acs.logging.engine.parser.ACSLogParser;
import alma.acs.logging.engine.parser.ACSLogParserFactory;
import alma.acs.util.IsoDateFormat;
import com.cosylab.logging.engine.ACS.ACSListenersDispatcher;
import com.cosylab.logging.engine.ACS.ACSLogRetrieval;
import com.cosylab.logging.engine.ACS.ACSRemoteLogListener;
import com.cosylab.logging.engine.ACS.ACSRemoteRawLogListener;
import com.cosylab.logging.engine.audience.Audience;
import com.cosylab.logging.engine.audience.OperatorAudience;
import com.cosylab.logging.engine.audience.Audience.AudienceInfo;
import com.cosylab.logging.engine.log.ILogEntry;
import com.cosylab.logging.engine.log.LogField;
import com.cosylab.logging.engine.log.LogTypeHelper;
import junit.framework.TestCase;
/**
* A class testing the filtering by mode performed by
* <code>ACSLogretrieval</code>.
* The mode is defined in <code>log_audience</code> ILD module.
*
* The test is done by checking what logs <code>ACSLogRetrieval</code> discards
* i.e. the <code>LCEngine</code> is not used here as it is stressed by
* other tests.
* This class is the listener for the log and the XMLs that <code>ACSLogRetrieval</code>
* sends to the listeners throw the <code>ACSListenersDispatcher</code>.
*
* @author acaproni
*
*/
public class EngineAudienceTest extends TestCase implements ACSRemoteLogListener, ACSRemoteRawLogListener {
/**
* The timeout (secs) to wait before giving up waiting for logs
*/
private final int TIMEOUT = 60;
// The header and footer to create log to fill the caches
public static final String logHeaderStr = " TimeStamp=\"";
public static final String logBodyStr = "\" Routine=\"CacheTest::testGet\" Host=\"this\" Process=\"test\" Thread=\"main\" Context=\"\" Audience=\"";
public static final String logEndOfBodyStr="\"><![CDATA[";
public static final String logFooterStr = "]]></";
/**
* The object whose filtering capabilities we want to test
*/
private ACSLogRetrieval logRetieval=null;
/**
* / The dispatcher used by <code>ACSLogRetrieval</code> to send logs to the
* registered listeners.
*/
private ACSListenersDispatcher dispatcher=null;
// The number of logs received in the callbacks
private int numOfReceivedLogs;
private int numOfReceivedXMLLogs;
// The audience under testing
// At the present only OPERATOR is implemented but the test has to check
// also the NO_AUDIENCE case
private Audience audience;
/* (non-Javadoc)
* @see junit.framework.TestCase#setUp()
*/
@Override
protected void setUp() throws Exception {
super.setUp();
numOfReceivedLogs=0;
numOfReceivedXMLLogs=0;
dispatcher = new ACSListenersDispatcher();
assertNotNull(dispatcher);
logRetieval = new ACSLogRetrieval(dispatcher);
assertNotNull(logRetieval);
logRetieval.setFilters(null);
logRetieval.start();
dispatcher.addLogListener(this);
dispatcher.addRawLogListener(this);
}
/* (non-Javadoc)
* @see junit.framework.TestCase#tearDown()
*/
@Override
protected void tearDown() throws Exception {
logRetieval.close(true);
dispatcher=null;
logRetieval=null;
super.tearDown();
}
/**
* Test the setting of the mode
*/
public void testSetMode() throws Exception {
// Set valid modes
logRetieval.setAudience(AudienceInfo.OPERATOR.getAudience());
assertEquals(AudienceInfo.OPERATOR.getAudience(), logRetieval.getAudience());
logRetieval.setAudience(AudienceInfo.SCILOG.getAudience());
assertEquals(AudienceInfo.SCILOG.getAudience(), logRetieval.getAudience());
logRetieval.setAudience(AudienceInfo.ENGINEER.getAudience());
assertEquals(AudienceInfo.ENGINEER.getAudience(), logRetieval.getAudience());
// Setting a null value should throw an exception
try {
logRetieval.setAudience(null);
} catch (Exception e) {
// OK
return;
}
throw new Exception("Null shuold not be accepted by ACSLogRetrieval.setAudience()");
}
/**
* Test the filtering for OPERATOR.
*
* The logs that should not be filtered are those that:
* - have a level of WARINING or greater
* - have the audience set to OPERATOR
*
* The test is done in 2 times:
* 1. a collection of logs with no audience is tested
* 2. a collection of logs with different values for audience
* is tested
*
* @throws Exception
*/
public void testOperatorModeFiltering() throws Exception {
audience=AudienceInfo.OPERATOR.getAudience();
logRetieval.setAudience(audience);
//
// Step 1: generate a collection of logs with no audience
//
// Generate 1000 log of each type
Collection<ILogEntry> logs = new Vector<ILogEntry>();
for (LogTypeHelper logType: LogTypeHelper.values()) {
if (logType!=LogTypeHelper.OFF) {
Collection<ILogEntry> tempLogs = CacheUtils.generateLogsType(1000, logType);
logs.addAll(tempLogs);
}
}
assertEquals(1000*(LogTypeHelper.values().length-1), logs.size());
for (ILogEntry log: logs) {
logRetieval.addLog(log.toXMLString());
}
// Wait until logRetrieval publish all the logs
assertFalse("Timeout waiting for logs", waitForLogs());
// Check the received logs
assertEquals(logs.size(), numOfReceivedXMLLogs);
assertEquals(1000*5,numOfReceivedLogs);
//
// Step 2: test a collection of logs with the audience
//
ACSLogParser parser = ACSLogParserFactory.getParser();
assertNotNull(parser);
SimpleDateFormat df = new IsoDateFormat();
assertNotNull(df);
// Generate 2 logs for each type.
// only one of them with audience OPERATOR
logs.clear();
for (LogTypeHelper logType: LogTypeHelper.values()) {
if (logType==LogTypeHelper.OFF) {
continue;
}
Date dt = new Date(System.currentTimeMillis());
StringBuffer dateSB = new StringBuffer();
FieldPosition pos = new FieldPosition(0);
df.format(dt,dateSB,pos);
StringBuilder logOperatorStr = new StringBuilder("<");
StringBuilder logNoOperatorStr = new StringBuilder();
// HSO 2009-11 No idea why this level translation is needed,
// but anyway I add the new level DELOUSE because it is similar to TRACE.
// (see COMP-3749 : JDK levels FINER and FINEST were previously mapped to TRACE, while now FINER maps to DELOUSE).
if (logType==LogTypeHelper.TRACE || logType==LogTypeHelper.DELOUSE) {
logType=LogTypeHelper.INFO;
}
logOperatorStr.append(logType.logEntryType);
logOperatorStr.append(logHeaderStr);
logOperatorStr.append(dateSB.toString());
logOperatorStr.append(logBodyStr);
// Insert the audience
logNoOperatorStr = new StringBuilder(logOperatorStr);
logOperatorStr.append(alma.log_audience.OPERATOR.value);
logNoOperatorStr.append(alma.log_audience.DEVELOPER.value);
logOperatorStr.append(logEndOfBodyStr);
logNoOperatorStr.append(logEndOfBodyStr);
logOperatorStr.append("LOG Txt>");
logNoOperatorStr.append("LOG Txt>");
logOperatorStr.append(logFooterStr);
logNoOperatorStr.append(logFooterStr);
logOperatorStr.append(logType.logEntryType);
logNoOperatorStr.append(logType.logEntryType);
logOperatorStr.append('>');
logNoOperatorStr.append('>');
ILogEntry logOp = parser.parse(logOperatorStr.toString());
logs.add(logOp);
ILogEntry logNoOp = parser.parse(logNoOperatorStr.toString());
logs.add(logNoOp);
}
assertEquals(2*(LogTypeHelper.values().length-1), logs.size());
numOfReceivedLogs=0;
numOfReceivedXMLLogs=0;
for (ILogEntry log: logs) {
logRetieval.addLog(log.toXMLString());
}
assertFalse("Timeout waiting for logs", waitForLogs());
assertEquals(logs.size(), numOfReceivedXMLLogs);
assertEquals(10, numOfReceivedLogs);
}
/**
* Test the case of ENGINEER i.e. no filtering
*
* @throws Exception
*/
public void testNoAudienceModeFiltering() throws Exception {
audience=AudienceInfo.ENGINEER.getAudience();
logRetieval.setAudience(audience);
Collection<ILogEntry> logs = CacheUtils.generateLogs(10000);
for (ILogEntry log: logs) {
logRetieval.addLog(log.toXMLString());
}
assertEquals(10000, logs.size());
assertFalse("Timeout waiting for logs", waitForLogs());
// All logs received or timeout
assertEquals(numOfReceivedXMLLogs, logs.size());
assertEquals(numOfReceivedLogs, logs.size());
}
/**
* Wait until the logRetrieval publishes all the logs
*
* @return true in case of timeout
*/
private boolean waitForLogs() {
int timeout=0;
int logsInQueue=0;
while (timeout<TIMEOUT && logRetieval.hasPendingEntries()) {
try {
Thread.sleep(250);
} catch (InterruptedException ie) {
continue;
}
if (logRetieval.size()!=logsInQueue) {
logsInQueue=logRetieval.size();
} else {
timeout++;
}
}
// We need to wait some more time because there is a critical race
// between the time the entry is removed from the EmgineCache
// and the time it is sent to listeners.
//
// @see EngineCache.size()
try {
Thread.sleep(1500);
} catch (InterruptedException ie) { }
return timeout>=TIMEOUT;
}
/**
* The counter <code>numOfReceivedXMLLogs</code> is incremented for each received log
*
* @see com.cosylab.logging.engine.ACS.ACSRemoteRawLogListener#xmlEntryReceived(java.lang.String)
*/
@Override
public void xmlEntryReceived(String xmlLogString) {
// Filtering does not apply to XML
numOfReceivedXMLLogs++;
}
/**
*
* The counter <code>numOfReceivedLogs</code> is incremented for each received log.
* The method write a message in the stdout if the received log does not match
* with the <code>audience</code>
*
* @see com.cosylab.logging.engine.ACS.ACSRemoteLogListener#logEntryReceived(com.cosylab.logging.engine.log.ILogEntry)
*/
@Override
public void logEntryReceived(ILogEntry logEntry) {
numOfReceivedLogs++;
if (audience instanceof OperatorAudience) {
if (logEntry.getType().ordinal()>=LogTypeHelper.WARNING.ordinal()) {
return;
}
String logStrAudience = (String)logEntry.getField(LogField.AUDIENCE);
String logAudience=alma.log_audience.OPERATOR.value;
if (!logStrAudience.equals(logAudience)) {
System.out.println("This log did not match for OPERATOR audience: "+logEntry.toString());
}
}
}
}