Attached is a test class mcs/class/corlib/Test/System/ExceptionTest.cs which implements an NUnit test case for the exception described previously. Also attached is the corresponding patch for System/AllTests.cs. The ExceptionTest class only tests for this one issue and so isn't a very good test of the Exception class as a whole. I don't know if you want to include stub tests like this or not.
Linus -----Original Message----- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]] On Behalf Of Linus Upson Sent: Saturday, May 04, 2002 2:39 PM To: [EMAIL PROTECTED] Subject: RE: [Mono-list] patch for mono/jit/exception.c I forgot to include the small test program which demonstrates the problem: using System; public class TryTest { public static void ThrowException() { throw new Exception(); } public static void Main() { ThrowException(); // If the following line is uncommented, mono will work right. // Console.WriteLine("This shouldn't matter"); try { Console.WriteLine("In try block"); } catch (Exception e) { Console.WriteLine("------------------------"); Console.WriteLine(e); Console.WriteLine("------------------------"); } } } Before the patch, the Exception thrown in ThrowException() would be caught by the catch block in Main(). Linus -----Original Message----- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]] On Behalf Of Linus Upson Sent: Saturday, May 04, 2002 2:09 PM To: [EMAIL PROTECTED] Subject: [Mono-list] patch for mono/jit/exception.c Running NUnitConsole_mono.exe in mono on Windows exposed the following bug: If an exception were throw by the instruction immediately preceding a try block, the exception would be considered to be thrown inside the try block. A patch is attached which appears to solve the problem. The patch won't work if arch_handle_exception() can be called with ctx->SC_EIP pointing to the instruction which threw the exception. I think an exception can only be thrown by a CALL (as far as managed code is concerned) so EIP will always point to the instruction after the CALL. If this isn't the case, a different fix will be needed. I believe the same problem exists on Linux as well, but I haven't tested. Cheers, Linus _______________________________________________ Mono-list maillist - [EMAIL PROTECTED] http://lists.ximian.com/mailman/listinfo/mono-list
//
// ExceptionTest.cs - NUnit Test Cases for the System.Exception class
//
// Linus Upson ([EMAIL PROTECTED])
//
using System;
using NUnit.Framework;
namespace MonoTests.System
{
public class ExceptionTest : TestCase
{
public ExceptionTest() : base ("MonoTests.System.ExceptionTest
testsuite") {}
public ExceptionTest(string name) : base(name) {}
public static ITest Suite {
get {
return new TestSuite(typeof(ExceptionTest));
}
}
// This test makes sure that exceptions thrown on block boundaries are
// handled in the correct block. The meaning of the 'caught' variable
is
// a little confusing since there are two catchers: the method being
// tested the the method calling the test. There is probably a better
// name, but I can't think of it right now.
public void TestThrowOnBlockBoundaries()
{
bool caught;
try {
caught = false;
ThrowBeforeTry();
} catch {
caught = true;
}
Assert("Exceptions thrown before try blocks should not be
caught", caught);
try {
caught = false;
ThrowAtBeginOfTry();
} catch {
caught = true;
}
Assert("Exceptions thrown at begin of try blocks should be
caught", !caught);
try {
caught = false;
ThrowAtEndOfTry();
} catch {
caught = true;
}
Assert("Exceptions thrown at end of try blocks should be
caught", !caught);
try {
caught = false;
ThrowAtBeginOfCatch();
} catch {
caught = true;
}
Assert("Exceptions thrown at begin of catch blocks should not
be caught", caught);
try {
caught = false;
ThrowAtEndOfCatch();
} catch {
caught = true;
}
Assert("Exceptions thrown at end of catch blocks should not be
caught", caught);
try {
caught = false;
ThrowAtBeginOfFinally();
} catch {
caught = true;
}
Assert("Exceptions thrown at begin of finally blocks should
not be caught", caught);
try {
caught = false;
ThrowAtEndOfFinally();
} catch {
caught = true;
}
Assert("Exceptions thrown at end of finally blocks should not
be caught", caught);
try {
caught = false;
ThrowAfterFinally();
} catch {
caught = true;
}
Assert("Exceptions thrown after finally blocks should not be
caught", caught);
}
private static void DoNothing()
{
}
private static void ThrowException()
{
throw new Exception();
}
private static void ThrowBeforeTry()
{
ThrowException();
try {
DoNothing();
} catch (Exception) {
DoNothing();
}
}
private static void ThrowAtBeginOfTry()
{
DoNothing();
try {
ThrowException();
DoNothing();
} catch (Exception) {
DoNothing();
}
}
private static void ThrowAtEndOfTry()
{
DoNothing();
try {
DoNothing();
ThrowException();
} catch (Exception) {
DoNothing();
}
}
private static void ThrowAtBeginOfCatch()
{
DoNothing();
try {
DoNothing();
ThrowException();
} catch (Exception) {
throw;
}
}
private static void ThrowAtEndOfCatch()
{
DoNothing();
try {
DoNothing();
ThrowException();
} catch (Exception) {
DoNothing();
throw;
}
}
private static void ThrowAtBeginOfFinally()
{
DoNothing();
try {
DoNothing();
ThrowException();
} catch (Exception) {
DoNothing();
} finally {
ThrowException();
DoNothing();
}
}
private static void ThrowAtEndOfFinally()
{
DoNothing();
try {
DoNothing();
ThrowException();
} catch (Exception) {
DoNothing();
} finally {
DoNothing();
ThrowException();
}
}
private static void ThrowAfterFinally()
{
DoNothing();
try {
DoNothing();
ThrowException();
} catch (Exception) {
DoNothing();
} finally {
DoNothing();
}
ThrowException();
}
}
}
System.AllTests.patch
Description: Binary data
