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();
                }
        }
}

Attachment: System.AllTests.patch
Description: Binary data

Reply via email to