/* * 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.io.File; import java.io.FileWriter; import java.util.Collection; import java.util.Iterator; import java.util.Properties; import java.util.Vector; import junit.framework.TestCase; import alma.acs.logging.engine.io.IOHelper; import alma.acs.logging.engine.io.IOPorgressListener; import alma.acs.logging.engine.parser.ACSLogParser; import alma.acs.logging.engine.parser.ACSLogParserFactory; import com.cosylab.logging.engine.ACS.ACSRemoteErrorListener; import com.cosylab.logging.engine.ACS.ACSRemoteLogListener; import com.cosylab.logging.engine.log.ILogEntry; import com.cosylab.logging.engine.log.ILogEntry.AdditionalData; import com.cosylab.logging.engine.log.LogField; /** * A class testing the load and save facilities * <P> * As a general rule, each test of this class * <OL> * <LI>generate some logs with the help of <code>CacheUtils</code>, * <LI>save and load the logs. * <LI>check if the logs written and those read are equals. * </OL> * * @author acaproni * */ public class LoadSaveTest extends TestCase implements IOPorgressListener, ACSRemoteLogListener, ACSRemoteErrorListener { // Some interesting logs to check // See COMP-2369 for log1 private final String log1 ="<Trace TimeStamp=\"2008-04-14T17:53:22.445\" SourceObject=\"CONTROL/ACC/cppContainer-GL\" "+ "File=\"Unavailable\" Line=\"0\" Routine=\"\" Host=\"gas01\" Process=\"CONTROL/ACC/cppContainer\" "+ "Context=\"\" Thread=\"CONTROL/Array002/DELAYSERVERServiceThread\">"+ "<![CDATA[AlarmSupplier::publishEvent()\n"+ "About to send XML of:\n"+ "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"+ "<ASI-message xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" backup=\"false\" version=\"0.9\" xsi:type=\"ASI-message\">\n"+ "<source-name>ALARM_SYSTEM_SOURCES</source-name>\n"+ "<source-hostname>gas01</source-hostname>\n"+ "<source-timestamp seconds=\"1208195602\" microseconds=\"433703\"/>\n"+ "<fault-states>\n"+ "<fault-state family=\"DelayServer\" member=\"CONTROL/Array002\" code=\"1\">\n"+ "<descriptor>TERMINATE</descriptor>\n"+ "<user-timestamp seconds=\"1208195602\" microseconds=\"433103\"/>\n"+ "</fault-state>\n"+ "</fault-states>\n"+ "</ASI-message>\n"+ "]]></Trace>\n"; private final String log2 = "<Warning TimeStamp=\"2005-12-13T15:09:12.041\" SourceObject=\"ARCHIVE_MASTER_COMP\" " + "File=\"alma.ACS.MasterComponentImpl.MasterComponentImplBase\" "+ "Line=\"164\" Routine=\"doTransition\" Host=\"gas\" Process=\"LoggerName: alma.component.ARCHIVE_MASTER_COMP\" "+ "Thread=\"RequestProcessor-10\" StackId=\"unknown\" StackLevel=\"0\" LogId=\"140\">"+ "<![CDATA[Illegal event.]]><Data Name=\"LoggedException\">alma.acs.genfw.runtime.sm.AcsStateIllegalEventException: illegal event 'initPass1' in state 'ONLINE'.\n"+ "at alma.ACS.MasterComponentImpl.statemachine.AlmaSubsystemContext.illegalEvent(AlmaSubsystemContext.java:248)\n"+ "at alma.ACS.MasterComponentImpl.statemachine.AvailableSubStateAbstract.initPass1(AvailableSubStateAbstract.java:30)\n"+ "at alma.ACS.MasterComponentImpl.statemachine.AvailableState.initPass1(AvailableState.java:60)\n"+ "at alma.ACS.MasterComponentImpl.statemachine.AlmaSubsystemContext.initPass1(AlmaSubsystemContext.java:135)\n"+ "at alma.ACS.MasterComponentImpl.MasterComponentImplBase.doTransition(MasterComponentImplBase.java:134)\n"+ "at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n"+ "at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n"+ "at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n"+ "at java.lang.reflect.Method.invoke(Method.java:324)\n"+ "at alma.acs.container.ContainerSealant.invoke(ContainerSealant.java:134)\n"+ "at $Proxy0.doTransition(Unknown Source)\n"+ "at alma.archive.ArchiveSubsystemMasterIFPOATie.doTransition(ArchiveSubsystemMasterIFPOATie.java:63)\n"+ "at alma.archive.ArchiveSubsystemMasterIFPOA._invoke(ArchiveSubsystemMasterIFPOA.java:76)\n"+ "at org.jacorb.poa.RequestProcessor.invokeOperation(Unknown Source)\n"+ "at org.jacorb.poa.RequestProcessor.process(Unknown Source)\n"+ "at org.jacorb.poa.RequestProcessor.run(Unknown Source)\n"+ "</Data></Warning>"; private String[] specialLogs = { log1, log2 }; // The number of bytes read and written private volatile long bytesRead, bytesWritten; /** * The logs to read and write */ private Collection<ILogEntry> logs; /** * The logs read form a file * <P> * This collection is filled by <code>logEntryReceived()</code>. */ private Vector<ILogEntry> logsRead; /** * The number of logs read since the beginning of a load */ private int numOfLogsRead; /** * The number of logs read since the beginning of a load */ private int numOfLogsWritten; /** * The number of logs in <code>logs</code> to load/save */ private static final int NUMBER_OF_LOGS=1500; /** * The directory where the logs are read and written. * <P> * It comes form the <code>user.dir</code> property. */ private String folder; private static final String USER_DIR = "user.dir"; /** * The name of the file used for testing */ private String fileName; /** * The name of the file used for testing compressed load and save */ private String gzipFileName; /** * @see alma.acs.logging.engine.io.IOPorgressListener#bytesRead(long) */ @Override public void bytesRead(long bytes) { bytesRead=bytes; } /** * @see alma.acs.logging.engine.io.IOPorgressListener#bytesWritten(long) */ @Override public void bytesWritten(long bytes) { bytesWritten=bytes; } /** * @see junit.framework.TestCase#setUp() */ @Override protected void setUp() throws Exception { super.setUp(); bytesRead=0; bytesWritten=0; numOfLogsRead=0; logs=CacheUtils.generateLogs(NUMBER_OF_LOGS); assertEquals(NUMBER_OF_LOGS, logs.size()); // Read the folder name and generate the file name Properties props = System.getProperties(); assertNotNull(props); folder = props.getProperty(USER_DIR); assertNotNull(folder); File folderFile = new File(folder); String folderPath = folderFile.getAbsolutePath(); fileName = folderPath+"/logs.xml"; gzipFileName=fileName+".gz"; // Check if folder is a writable directory assertTrue(folderFile.isDirectory()); assertTrue(folderFile.canWrite()); logsRead = new Vector<ILogEntry>(); } /** * @see junit.framework.TestCase#tearDown() */ @Override protected void tearDown() throws Exception { super.tearDown(); // Delete the file File f = new File(fileName); f.deleteOnExit(); // Delete the compressed file File compressed = new File(fileName+".gz"); if (compressed.exists()) { compressed.deleteOnExit(); } logs.clear(); logs=null; logsRead.clear(); logsRead=null; } /** * Load and save a collection of logs in uncompressed files * <P> * The save is performed by passing the name of the file * * @throws Exception */ public void testSaveLoad() throws Exception { IOHelper ioHelper = new IOHelper(); assertNotNull(ioHelper); long assumedLen=0; for (ILogEntry log: logs) { char[] chars = (log.toXMLString()+"\n").toCharArray(); assumedLen+=chars.length; } // Save the logs on file ioHelper.saveLogs(fileName, logs, this, false,false); assertEquals(assumedLen, bytesWritten); assertEquals(logs.size(), numOfLogsWritten); // Read the logs ioHelper.loadLogs(fileName, this, null, this, this,false); assertEquals(logs.size(),numOfLogsRead); assertTrue(bytesRead>assumedLen); // bytes read includes the XML header // Compare the 2 collections assertEquals(logs.size(), logsRead.size()); int t=0; for (ILogEntry log: logs) { String logXML = log.toXMLString(); String logReadXML = logsRead.get(t++).toXMLString(); assertEquals(logXML, logReadXML); } } /** * Load and save a collection of logs in uncompressed files * <P> * The save is performed by passing the name of the file * * @throws Exception */ public void testSaveLoadCompressed() throws Exception { IOHelper ioHelper = new IOHelper(); assertNotNull(ioHelper); // Save the logs on file ioHelper.saveLogs(gzipFileName, logs, this, false,true); assertEquals(logs.size(), numOfLogsWritten); // Read the logs ioHelper.loadLogs(gzipFileName, this, null, this, this,true); assertEquals(logs.size(),numOfLogsRead); // Compare the 2 collections assertEquals(logs.size(), logsRead.size()); // Compare the 2 collections int t=0; for (ILogEntry log: logs) { String logXML = log.toXMLString(); String logReadXML = logsRead.get(t++).toXMLString(); assertEquals(logXML, logReadXML); } } /** * @see com.cosylab.logging.engine.ACS.ACSRemoteErrorListener#errorReceived(java.lang.String) */ @Override public void errorReceived(String xml) { System.err.println("ERROR: "+xml); } /** * @see com.cosylab.logging.engine.ACS.ACSRemoteLogListener#logEntryReceived(com.cosylab.logging.engine.log.ILogEntry) */ @Override public void logEntryReceived(ILogEntry logEntry) { logsRead.add(logEntry); } /** * @see alma.acs.logging.engine.io.IOPorgressListener#logsRead(int) */ @Override public void logsRead(int numOfLogs) { numOfLogsRead=numOfLogs; } /** * @see alma.acs.logging.engine.io.IOPorgressListener#logsWritten(int) */ @Override public void logsWritten(int numOfLogs) { numOfLogsWritten=numOfLogs; } /** * Load a set of special logs that could be interesting. * <P> * Initially this method opens an XML file and writes into it the special logs without using * <code>IOHelper</code>. * Then it tries to load the file containing the special logs * * * @throws Exception */ public void testLoadingSpecialLogs() throws Exception { FileWriter f = new FileWriter(fileName,false); f.write("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<Log>\n<Header Name=\"NameForXmlDocument\" Type=\"LOGFILE\" />\n"); for (String xml: specialLogs) { f.write(xml); } f.write("</Log>"); f.flush(); f.close(); IOHelper ioHelper = new IOHelper(); assertNotNull(ioHelper); ioHelper.loadLogs(fileName, this, null, this, this,false); // Check if the number of records is the same assertEquals(specialLogs.length, logsRead.size()); } /** * Test the append switch while saving logs by saving the same * collection twice in the same file but with the append switch set to * <code>true</code>. * @throws Exception */ public void testAppend() throws Exception { IOHelper ioHelper = new IOHelper(); assertNotNull(ioHelper); // First save with no append ioHelper.saveLogs(fileName, logs, this, false,false); // Second save with append ioHelper.saveLogs(fileName, logs, this, true,false); // Load the logs ioHelper.loadLogs(fileName, this, null, this, this,false); assertEquals(2*logs.size(), logsRead.size()); assertEquals(2*logs.size(), numOfLogsRead); } /** * Check the load and save of logs by passing an <code>Iterator</code> * * @throws Exception */ public void testSaveLoadIterator() throws Exception { IOHelper ioHelper = new IOHelper(); assertNotNull(ioHelper); Iterator<ILogEntry> iterator = logs.iterator(); long assumedLen=0; for (ILogEntry log: logs) { char[] chars = (log.toXMLString()+"\n").toCharArray(); assumedLen+=chars.length; } // Save the logs on file ioHelper.saveLogs(fileName, iterator, this, false,false); assertEquals(assumedLen, bytesWritten); assertEquals(logs.size(), numOfLogsWritten); // Read the logs ioHelper.loadLogs(fileName, this, null, this, this,false); assertEquals(logs.size(),numOfLogsRead); } /** * Save and Load the special logs then check their fields. * <P> * This test is performed comparing the fields of the special logs one by one * instead of comparing the XMLs. * The test does the following steps: * <OL> * <LI>build vector of logs to save from the XMLs in <code>specialLogs</code> * <LI>save the vector of logs with an <code>IOHelper</code> object * <LI>load the logs from file * <LI>compare each field of the logs read from the file with those in <code>specialLogs</code> * <LI>compare the additional data names and values * </OL> * <P> * The test implicitly checks the conversion between XML and ILogEntry too. */ public void testSaveLoadFields() throws Exception { ACSLogParser parser = ACSLogParserFactory.getParser(); assertNotNull(parser); //Build the logs from the XML Vector<ILogEntry> logsToCheck = new Vector<ILogEntry>(); for (int t=0; t<specialLogs.length; t++) { ILogEntry log =parser.parse(specialLogs[t]); assertNotNull(log); logsToCheck.add(log); } // Save the logs on disk IOHelper ioHelper = new IOHelper(); assertNotNull(ioHelper); ioHelper.saveLogs(fileName, logsToCheck, this, false,false); assertEquals(logsToCheck.size(), numOfLogsWritten); // Load the logs from disk ioHelper.loadLogs(fileName, this, null, this, this,false); assertEquals(logsRead.size(),logsToCheck.size()); // Iterate over the logs comparing each field for (int t=0; t<logsToCheck.size(); t++) { ILogEntry originalLog = logsToCheck.elementAt(t); assertNotNull(originalLog); ILogEntry savedLog = logsRead.elementAt(t); assertNotNull(savedLog); // Check the fields for (LogField f: LogField.values()) { Object original= originalLog.getField(f); Object saved=savedLog.getField(f); assertEquals("Fields "+f+" differ",original, saved); } // Check additional data assertEquals(originalLog.hasDatas(), savedLog.hasDatas()); if (originalLog.hasDatas()) { Vector<AdditionalData> originalData = originalLog.getAdditionalData(); assertNotNull(originalData); Vector<AdditionalData> savedData = savedLog.getAdditionalData(); assertNotNull(savedData); assertEquals(originalData.size(), savedData.size()); for (int count=0; count<originalData.size(); count++) { AdditionalData originalDataItem = originalData.elementAt(count); assertNotNull(originalDataItem); AdditionalData savedDataItem = savedData.elementAt(count); assertNotNull(savedDataItem); assertEquals("Data names differ", originalDataItem.name, savedDataItem.name); assertEquals("Data values differ", originalDataItem.value, savedDataItem.value); } } } } }