/*
* 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.acs.exceptions;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.InetAddress;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import junit.framework.TestCase;
import alma.ACSErr.ACSErrTypeTest;
import alma.ACSErr.Completion;
import alma.ACSErr.ErrorTrace;
import alma.ACSErr.Severity;
import alma.ACSErrTypeTest.ACSErrTest0;
import alma.ACSErrTypeTest.ACSErrTest3;
import alma.ACSErrTypeTest.ACSErrTestOK;
import alma.ACSErrTypeTest.wrappers.ACSErrTest1AcsJCompletion;
import alma.ACSErrTypeTest.wrappers.ACSErrTest2AcsJCompletion;
import alma.ACSErrTypeTest.wrappers.ACSErrTest3AcsJCompletion;
import alma.ACSErrTypeTest.wrappers.ACSErrTestOKAcsJCompletion;
import alma.ACSErrTypeTest.wrappers.AcsJACSErrTest0Ex;
import alma.ACSErrTypeTest.wrappers.AcsJACSErrTest1Ex;
import alma.ACSErrTypeTest.wrappers.AcsJACSErrTest2Ex;
import alma.ACSErrTypeTest.wrappers.AcsJACSErrTest3Ex;
import alma.acs.testsupport.LogRecordCollectingLogger;
import alma.acs.util.UTCUtility;
/**
* Tests for {@link AcsJException}, {@link alma.acs.exceptions.AcsJCompletion}
* and the generated example subclasses.
*
* @author hsommer Jun 18, 2003 3:54:40 PM
*/
public class AcsJExceptionTest extends TestCase
{
private ClientServerExceptionExample exSystem;
private String hostName;
public AcsJExceptionTest() throws Exception {
super("AcsJExceptionTest");
exSystem = new ClientServerExceptionExample();
hostName = InetAddress.getLocalHost().getHostName();
}
/**
* Uses {@link ClientServerExceptionExample#throwOriginalAcsJACSErrTest0Ex} to verify the output
* of the method {@link AcsJException#getErrorTrace}.
* Thus what gets tested is the conversion from the AcsJ- to the CORBA world.
* <P>
* Fields which are more difficult to get out from an ErrorTrace object will
* be checked in subsequent tests.
*/
public void testGetErrorTrace()
{
try
{
exSystem.throwOriginalAcsJACSErrTest0Ex();
}
catch (AcsJException e)
{
ErrorTrace et = e.getErrorTrace();
assertNotNull("errorTrace obj not null", et);
ErrorTrace[] prev = et.previousError;
assertNotNull("chained child ex", prev);
assertEquals("1 chained child ex", 1, prev.length);
assertEquals("no grandchild ex", 0, prev[0].previousError.length);
// check data of ErrorTrace that was constructed from a non-ACS exception
assertEquals("time stamp for non-ACS exceptions should be defaulted to be 1 millisec less than the parent's time stamp",
et.timeStamp-10000, prev[0].timeStamp);
}
}
/**
* Tests the conversion from {@link AcsJACSErrTest0Ex}
* to {@link ErrorTrace} and back, first by wrapping and later by directly
* converting a CORBA exception with/to a native Java exception.
* <p>
* Calls {@link ClientServerExceptionExample#throwWrapperAcsJACSErrTest0Ex} and
* {@link ClientServerExceptionExample#throwConvertedAcsJACSErrTest0Ex} to get the
* three linked exceptions
* <ul>
* <li> <code>AcsJACSErrTest0Ex</code> thrown locally ("client side"),
* only in case of <code>throwWrapperAcsJACSErrTest0Ex</code>
* <li> <code>AcsJException</code> caused by a
* <code>NullPointerException</code>, both thrown "remotely"
* in the implementation of the "server side" method
* {@link ClientServerExceptionExample#throwACSErrTest0Ex}
* and translated back and forth from an <code>ErrorTrace</code>
* </ul>
* Checks that the exceptions are correctly chained up
* and the data is correct.
*/
public void testErrorTraceToAcsJExConversion()
{
// first the variant with a new exception created on the client side,
// and with explicit extraction of the ErrorTrace object from the CORBA exception
try {
exSystem.throwWrapperAcsJACSErrTest0Ex(false);
}
catch (AcsJACSErrTest0Ex ex1) {
checkWrapperAcsJEx(ex1);
}
// same as above, but with the variation of
// automatic extraction of the ErrorTrace object from the CORBA exception
try {
exSystem.throwWrapperAcsJACSErrTest0Ex(true);
}
catch (AcsJACSErrTest0Ex ex2) {
checkWrapperAcsJEx(ex2);
}
// next we try the client-side conversion instead of wrapping
try
{
exSystem.throwConvertedAcsJACSErrTest0Ex();
}
catch (AcsJException e)
{
assertTrue(e instanceof AcsJACSErrTest0Ex);
assertEquals("low level ex", e.getMessage());
assertEquals(2, e.getTraceDepth());
assertEquals("Poverty", e.getProperty("MyStupidProperty"));
Throwable cause1 = e.getCause();
assertNotNull(cause1);
assertTrue(cause1 instanceof DefaultAcsJException);
assertEquals("mean NPE", cause1.getMessage());
assertEquals("java.lang.NullPointerException", ((AcsJException)cause1).getShortDescription());
DefaultAcsJException acsJCause1 = (DefaultAcsJException) cause1;
assertEquals(1, acsJCause1.getTraceDepth());
}
}
/**
* Checks the structure and values of the exception obtained from
* {@link ClientServerExceptionExample#throwWrapperAcsJACSErrTest0Ex(boolean)}.
* @param ex
*/
private void checkWrapperAcsJEx(AcsJACSErrTest0Ex ex) {
assertEquals("remote call failed", ex.getMessage());
assertEquals("ClientServerExceptionExample.java", ex.getFile());
assertEquals(3, ex.getTraceDepth());
assertEquals(hostName, ex.getHost());
String threadName = ex.getThreadName();
assertNotNull(threadName);
assertTrue(threadName.trim().length() > 0);
assertTrue(ex.getLine() > 0);
assertNotNull(ex.getMethod());
assertTrue(ex.getMethod().trim().length() > 0);
assertEquals(Severity.Error, ex.getSeverity());
Throwable cause1 = ex.getCause();
assertNotNull(cause1);
assertTrue(cause1 instanceof AcsJACSErrTest0Ex && cause1 != ex);
assertEquals("low level ex", cause1.getMessage());
AcsJACSErrTest0Ex acsJCause1 = (AcsJACSErrTest0Ex) cause1;
assertEquals("ClientServerExceptionExample.java", acsJCause1.getFile());
assertEquals("Poverty", acsJCause1.getProperty("MyStupidProperty"));
assertEquals(2, acsJCause1.getTraceDepth());
long timeCause1 = acsJCause1.getTimestampMillis();
assertEquals("ClientServerExceptionExample.java", acsJCause1.getFile());
assertEquals(hostName, acsJCause1.getHost());
assertEquals(threadName, acsJCause1.getThreadName());
assertTrue(acsJCause1.getLine() > 0);
assertNotNull(acsJCause1.getMethod());
assertTrue(acsJCause1.getMethod().trim().length() > 0);
assertEquals(Severity.Error, acsJCause1.getSeverity());
Throwable cause2 = cause1.getCause();
assertNotNull(cause2);
assertTrue(cause2 instanceof DefaultAcsJException);
assertEquals("mean NPE", cause2.getMessage());
assertEquals("java.lang.NullPointerException", ((DefaultAcsJException)cause2).getShortDescription());
DefaultAcsJException acsJCause2 = (DefaultAcsJException) cause2;
assertEquals("ClientServerExceptionExample.java", acsJCause2.getFile());
assertEquals(timeCause1 - 1, acsJCause2.getTimestampMillis());
assertEquals(1, acsJCause2.getTraceDepth());
assertEquals(hostName, acsJCause2.getHost());
assertEquals("NA", acsJCause2.getThreadName()); // NPE did not carry thread name info
assertTrue(acsJCause2.getLine() > 0);
assertNotNull(acsJCause2.getMethod());
assertTrue(acsJCause2.getMethod().trim().length() > 0);
assertEquals(Severity.Error, acsJCause2.getSeverity());
}
/**
* Creates Completion objects from scratch, from other completion objects,
* with and without associated exception, and checks the values.
*/
public void testJCompletion()
{
// a completion without associated exception
AcsJCompletion jcompl1 = new ACSErrTestOKAcsJCompletion();
assertEquals(ACSErrTypeTest.value, jcompl1.getType());
assertEquals(ACSErrTestOK.value, jcompl1.getCode());
assertFalse(jcompl1.isError());
assertTrue(jcompl1.getTimeStamp() > 0);
Completion corbacompl = jcompl1.toCorbaCompletion();
assertEquals(ACSErrTypeTest.value, corbacompl.type);
assertEquals(ACSErrTestOK.value, corbacompl.code);
assertTrue(corbacompl.previousError.length == 0);
assertEquals(UTCUtility.utcJavaToOmg(jcompl1.getTimeStamp()), corbacompl.timeStamp);
long timeMillisBeforeExceptionCreation = System.currentTimeMillis();
// completion with associated exception,
// trying to wrap the previous completion (which has no exception that could be wrapped)
AcsJCompletion jcompl2 = new ACSErrTest1AcsJCompletion(jcompl1);
assertTrue(jcompl2.isError());
AcsJException acsjex2 = jcompl2.getAcsJException();
assertTrue(acsjex2 instanceof AcsJACSErrTest1Ex);
assertNull(acsjex2.getCause());
// completion with associated exception,
// but this time trying to wrap the plain CORBA completion instead of its AcsJ-equivalent.
AcsJCompletion jcompl2b = new ACSErrTest2AcsJCompletion(corbacompl);
assertTrue(jcompl2b.isError());
AcsJException acsjex2b = jcompl2b.getAcsJException();
assertTrue(acsjex2b instanceof AcsJACSErrTest2Ex);
assertNull(acsjex2b.getCause());
// now wrapping a completion with exception with another completion with exception
AcsJCompletion jcompl3 = new ACSErrTest3AcsJCompletion(jcompl2);
assertTrue(jcompl3.isError());
AcsJException acsjex3 = jcompl3.getAcsJException();
assertTrue(acsjex3 instanceof AcsJACSErrTest3Ex);
Throwable acsjex_cause = acsjex3.getCause();
assertNotNull(acsjex_cause);
Throwable acsjex_cause2 = acsjex_cause.getCause();
assertNull(acsjex_cause2);
Completion corbacomp3 = jcompl3.toCorbaCompletion();
assertEquals(ACSErrTypeTest.value, corbacomp3.type);
assertEquals(ACSErrTest3.value, corbacomp3.code);
assertNotNull(corbacomp3.previousError);
assertEquals(1, corbacomp3.previousError.length);
ErrorTrace trace_3_1 = corbacomp3.previousError[0];
assertNotNull(trace_3_1);
ErrorTrace trace_3_0 = trace_3_1.previousError[0];
assertNotNull(trace_3_0);
assertEquals(0, trace_3_0.previousError.length);
// check the various timestamps
long timeMillisAfterExceptionCreation = System.currentTimeMillis();
assertTrue(timeMillisBeforeExceptionCreation <= acsjex2.getTimestampMillis());
assertTrue(timeMillisAfterExceptionCreation >= acsjex2.getTimestampMillis());
assertTrue(timeMillisBeforeExceptionCreation <= acsjex2b.getTimestampMillis());
assertTrue(timeMillisAfterExceptionCreation >= acsjex2b.getTimestampMillis());
long corbacomp3_millis = UTCUtility.utcOmgToJava(corbacomp3.timeStamp);
assertTrue(timeMillisBeforeExceptionCreation <= corbacomp3_millis);
assertTrue(timeMillisAfterExceptionCreation >= corbacomp3_millis);
long trace_3_0_millis = UTCUtility.utcOmgToJava(trace_3_0.timeStamp);
assertTrue(timeMillisBeforeExceptionCreation <= trace_3_0_millis);
assertTrue(timeMillisAfterExceptionCreation >= trace_3_0_millis);
}
/**
* Checks if logging of ACS exceptions (including caused-by exceptions) works.
* Here "logging" refers to special logging via
* {@link AcsJException#log(java.util.logging.Logger)}.
* <p>
* See also <code>alma.demo.client.XmlComponentClient#testException()</code> in module jcontexmpl.
*/
public void testLogAcsJException() {
LogRecordCollectingLogger logger = LogRecordCollectingLogger.getCollectingLogger("AcsJExceptionTest-Logger");
long timeBefore = System.currentTimeMillis();
try {
exSystem.throwWrapperAcsJACSErrTest0Ex(true);
} catch (AcsJACSErrTest0Ex e) {
long timeAfter = System.currentTimeMillis();
assertEquals(3, e.getTraceDepth());
String firstLogMsg = "Will log exception coming from throwWrapperAcsJACSErrTest0Ex";
logger.info(firstLogMsg);
e.log(logger);
LogRecord[] logRecords = logger.getCollectedLogRecords();
assertNotNull(logRecords);
assertEquals(4, logRecords.length);
assertEquals(firstLogMsg, logRecords[0].getMessage());
// The top-level exception is logged first, with stack level = 2
LogRecord lr2 = logRecords[1];
assertEquals("Test error 0 (type=" + ACSErrTypeTest.value + ", code=" + ACSErrTest0.value + ") :: remote call failed", lr2.getMessage());
assertTrue(lr2.getMillis() >= timeBefore);
assertTrue(lr2.getMillis() <= timeAfter);
Map logProperties = (Map) lr2.getParameters()[0];
assertTrue(logProperties.containsKey("Line"));
assertTrue(logProperties.containsKey("ThreadName"));
assertEquals(hostName, logProperties.get("HostName"));
assertEquals("throwWrapperAcsJACSErrTest0Ex", lr2.getSourceMethodName());
final String stackId = (String) logProperties.get("StackId");
assertNotNull(stackId);
assertEquals(2, ((Long)logProperties.get("StackLevel")).intValue());
Map userProps2 = (Map) lr2.getParameters()[1];
assertEquals(0, userProps2.size());
// The causing exception is logged next, with stack level = 1
LogRecord lr1 = logRecords[2];
String msg1 = lr1.getMessage();
assertEquals("Test error 0 (type=" + ACSErrTypeTest.value + ", code=" + ACSErrTest0.value + ") :: low level ex", msg1);
assertTrue(lr1.getMillis() >= timeBefore);
assertTrue(lr1.getMillis() <= timeAfter);
logProperties = (Map) lr1.getParameters()[0];
assertTrue(logProperties.containsKey("Line"));
assertTrue(logProperties.containsKey("ThreadName"));
assertEquals(hostName, logProperties.get("HostName"));
assertEquals("throwOriginalAcsJACSErrTest0Ex", lr1.getSourceMethodName());
assertEquals(stackId, logProperties.get("StackId"));
assertEquals(1, ((Long)logProperties.get("StackLevel")).intValue());
Map userProps1 = (Map) lr1.getParameters()[1];
assertEquals(1, userProps1.size());
assertEquals("Poverty", userProps1.get("MyStupidProperty"));
// last comes the wrapped NullPointerException, with stack level = 0
LogRecord lr0 = logRecords[3];
String msg0 = lr0.getMessage();
assertEquals("java.lang.NullPointerException (type=0, code=0) :: mean NPE", msg0);
logProperties = (Map) lr0.getParameters()[0];
assertTrue(logProperties.containsKey("Line"));
assertTrue(logProperties.containsKey("ThreadName"));
assertEquals(hostName, logProperties.get("HostName"));
assertEquals("throwOriginalAcsJACSErrTest0Ex", lr0.getSourceMethodName());
assertEquals(stackId, logProperties.get("StackId"));
assertEquals(0, ((Long)logProperties.get("StackLevel")).intValue());
Map userProps0 = (Map) lr0.getParameters()[1];
assertEquals(0, userProps0.size());
}
}
/**
* Tests how an exception is logged via the standard method {@link Logger#log(Level, String, Throwable)}.
* In particular, this test verifies that also JDK (= non-AcsJ) exceptions are correctly transformed
* into Corba-style ACS exceptions and back.
*/
public void testStackTraceLog() {
try {
exSystem.throwConvertedAcsJACSErrTest0Ex();
} catch (AcsJACSErrTest0Ex jex) {
// This jex has already gone from AcsJ to Corba to AcsJ.
// Just to be sure we catch all possible issues, we do another round of conversion here
AcsJACSErrTest0Ex jex2 = AcsJACSErrTest0Ex.fromACSErrTest0Ex(
jex.toACSErrTest0Ex()
);
// Check the stack (should be the original location)
StringWriter wr = new StringWriter();
jex2.printStackTrace(new PrintWriter(wr));
String linesep = System.getProperty("line.separator");
String expectedTrace = "alma.ACSErrTypeTest.wrappers.AcsJACSErrTest0Ex: low level ex [ MyStupidProperty='Poverty' ] " + linesep
+ " at ---.throwOriginalAcsJACSErrTest0Ex(ClientServerExceptionExample.java:48)" + linesep
+ "Caused by: alma.acs.exceptions.DefaultAcsJException (java.lang.NullPointerException): mean NPE" + linesep
+ " at ---.throwOriginalAcsJACSErrTest0Ex(ClientServerExceptionExample.java:47)" + linesep;
assertEquals(expectedTrace, wr.toString());
}
}
}