X Tutup
using System; using NUnit.Framework; using Python.Runtime; namespace Python.EmbeddingTest { public class TestPythonException { [Test] public void TestMessage() { var list = new PyList(); PyObject foo = null; var ex = Assert.Throws(() => foo = list[0]); Assert.AreEqual("list index out of range", ex.Message); Assert.IsNull(foo); } [Test] public void TestType() { var list = new PyList(); PyObject foo = null; var ex = Assert.Throws(() => foo = list[0]); Assert.AreEqual("IndexError", ex.Type.Name); Assert.IsNull(foo); } [Test] public void TestNoError() { // There is no PyErr to fetch Assert.Throws(() => PythonException.FetchCurrentRaw()); var currentError = PythonException.FetchCurrentOrNullRaw(); Assert.IsNull(currentError); } [Test] public void TestNestedExceptions() { try { PythonEngine.Exec(@" try: raise Exception('inner') except Exception as ex: raise Exception('outer') from ex "); } catch (PythonException ex) { Assert.That(ex.InnerException, Is.InstanceOf()); Assert.That(ex.InnerException.Message, Is.EqualTo("inner")); } } [Test] public void InnerIsEmptyWithNoCause() { var list = new PyList(); PyObject foo = null; var ex = Assert.Throws(() => foo = list[0]); Assert.IsNull(ex.InnerException); } [Test] public void TestPythonExceptionFormat() { try { PythonEngine.Exec("raise ValueError('Error!')"); Assert.Fail("Exception should have been raised"); } catch (PythonException ex) { // Console.WriteLine($"Format: {ex.Format()}"); // Console.WriteLine($"Stacktrace: {ex.StackTrace}"); Assert.That( ex.Format(), Does.Contain("Traceback") .And.Contains("(most recent call last):") .And.Contains("ValueError: Error!") ); // Check that the stacktrace is properly formatted Assert.That( ex.StackTrace, Does.Not.StartWith("[") .And.Not.Contain("\\n") ); } } [Test] public void TestPythonExceptionFormatNoTraceback() { try { var module = PyModule.Import("really____unknown___module"); Assert.Fail("Unknown module should not be loaded"); } catch (PythonException ex) { // ImportError/ModuleNotFoundError do not have a traceback when not running in a script Assert.AreEqual(ex.StackTrace, ex.Format()); } } [Test] public void TestPythonExceptionFormatNormalized() { try { PythonEngine.Exec("a=b\n"); Assert.Fail("Exception should have been raised"); } catch (PythonException ex) { Assert.AreEqual("Traceback (most recent call last):\n File \"\", line 1, in \nNameError: name 'b' is not defined\n", ex.Format()); } } [Test] public void TestPythonException_PyErr_NormalizeException() { using (var scope = Py.CreateScope()) { scope.Exec(@" class TestException(NameError): def __init__(self, val): super().__init__(val) x = int(val)"); Assert.IsTrue(scope.TryGet("TestException", out PyObject type)); PyObject str = "dummy string".ToPython(); var typePtr = new NewReference(type.Reference); var strPtr = new NewReference(str.Reference); var tbPtr = new NewReference(Runtime.Runtime.None.Reference); Runtime.Runtime.PyErr_NormalizeException(ref typePtr, ref strPtr, ref tbPtr); using var typeObj = typePtr.MoveToPyObject(); using var strObj = strPtr.MoveToPyObject(); using var tbObj = tbPtr.MoveToPyObject(); // the type returned from PyErr_NormalizeException should not be the same type since a new // exception was raised by initializing the exception Assert.IsFalse(PythonReferenceComparer.Instance.Equals(type, typeObj)); // the message should now be the string from the throw exception during normalization Assert.AreEqual("invalid literal for int() with base 10: 'dummy string'", strObj.ToString()); } } [Test] public void TestPythonException_Normalize_ThrowsWhenErrorSet() { Exceptions.SetError(Exceptions.TypeError, "Error!"); var pythonException = PythonException.FetchCurrentRaw(); Exceptions.SetError(Exceptions.TypeError, "Another error"); Assert.Throws(() => pythonException.Normalize()); Exceptions.Clear(); } } }
X Tutup