chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Constraints;
|
||||
using Python.Runtime;
|
||||
using QuantConnect.Exceptions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Tests.Common.Exceptions
|
||||
{
|
||||
[TestFixture]
|
||||
public class ClrBubbledExceptionInterpreterTests
|
||||
{
|
||||
private string _pythonModuleName = "Test_PythonExceptionInterpreter";
|
||||
private ClrBubbledException _dotnetException;
|
||||
private PythonException _pythonException;
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void Setup()
|
||||
{
|
||||
using (Py.GIL())
|
||||
{
|
||||
var module = Py.Import(_pythonModuleName);
|
||||
dynamic algorithm = module.GetAttr("Test_PythonExceptionInterpreter").Invoke();
|
||||
|
||||
try
|
||||
{
|
||||
// self.MarketOrder(null, 1)
|
||||
algorithm.dotnet_error();
|
||||
}
|
||||
catch (ClrBubbledException e)
|
||||
{
|
||||
_dotnetException = e;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// x = 1 / 0
|
||||
algorithm.zero_division_error();
|
||||
}
|
||||
catch (PythonException e)
|
||||
{
|
||||
_pythonException = e;
|
||||
}
|
||||
|
||||
Assert.IsNotNull(_dotnetException);
|
||||
Assert.IsNotNull(_pythonException);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(typeof(Exception), ExpectedResult = false)]
|
||||
[TestCase(typeof(KeyNotFoundException), ExpectedResult = false)]
|
||||
[TestCase(typeof(DivideByZeroException), ExpectedResult = false)]
|
||||
[TestCase(typeof(InvalidOperationException), ExpectedResult = false)]
|
||||
[TestCase(typeof(PythonException), ExpectedResult = false)]
|
||||
[TestCase(typeof(ClrBubbledException), ExpectedResult = true)]
|
||||
public bool CanInterpretReturnsTrueOnlyForClrBubbledExceptionType(Type exceptionType)
|
||||
{
|
||||
var exception = CreateExceptionFromType(exceptionType);
|
||||
return new ClrBubbledExceptionInterpreter().CanInterpret(exception);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(typeof(Exception), true)]
|
||||
[TestCase(typeof(KeyNotFoundException), true)]
|
||||
[TestCase(typeof(DivideByZeroException), true)]
|
||||
[TestCase(typeof(InvalidOperationException), true)]
|
||||
[TestCase(typeof(PythonException), true)]
|
||||
[TestCase(typeof(ClrBubbledException), false)]
|
||||
public void InterpretThrowsForNonClrBubbledExceptionTypes(Type exceptionType, bool expectThrow)
|
||||
{
|
||||
var exception = CreateExceptionFromType(exceptionType);
|
||||
var interpreter = new ClrBubbledExceptionInterpreter();
|
||||
var constraint = expectThrow ? (IResolveConstraint)Throws.Exception : Throws.Nothing;
|
||||
Assert.That(() => interpreter.Interpret(exception, NullExceptionInterpreter.Instance), constraint);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VerifyMessageContainsStackTraceInformation()
|
||||
{
|
||||
var exception = CreateExceptionFromType(typeof(ClrBubbledException));
|
||||
var assembly = typeof(ClrBubbledExceptionInterpreter).Assembly;
|
||||
var interpreter = StackExceptionInterpreter.CreateFromAssemblies();
|
||||
exception = interpreter.Interpret(exception, NullExceptionInterpreter.Instance);
|
||||
|
||||
Assert.True(exception.Message.Contains("Object reference not set to an instance of an object.", StringComparison.InvariantCulture));
|
||||
Assert.True(exception.Message.Contains("at dotnet_error", StringComparison.InvariantCulture));
|
||||
Assert.True(exception.Message.Contains("self.market_order(None", StringComparison.InvariantCulture));
|
||||
Assert.True(exception.Message.Contains($"in {_pythonModuleName}.py: line ", StringComparison.InvariantCulture));
|
||||
}
|
||||
|
||||
private Exception CreateExceptionFromType(Type type)
|
||||
{
|
||||
if (type == typeof(ClrBubbledException))
|
||||
{
|
||||
return _dotnetException;
|
||||
}
|
||||
|
||||
return type == typeof(PythonException) ? _pythonException : (Exception)Activator.CreateInstance(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Constraints;
|
||||
using QuantConnect.Exceptions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Tests.Common.Exceptions
|
||||
{
|
||||
[TestFixture]
|
||||
public class DllNotFoundPythonExceptionInterpreterTests
|
||||
{
|
||||
[Test]
|
||||
[TestCase(typeof(Exception), ExpectedResult = false)]
|
||||
[TestCase(typeof(KeyNotFoundException), ExpectedResult = false)]
|
||||
[TestCase(typeof(DivideByZeroException), ExpectedResult = false)]
|
||||
[TestCase(typeof(InvalidOperationException), ExpectedResult = false)]
|
||||
[TestCase(typeof(DllNotFoundException), ExpectedResult = true)]
|
||||
public bool CanInterpretReturnsTrueForOnlyDllNotFoundExceptionType(Type exceptionType)
|
||||
{
|
||||
var exception = CreateExceptionFromType(exceptionType);
|
||||
return new DllNotFoundPythonExceptionInterpreter().CanInterpret(exception);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(typeof(Exception), true)]
|
||||
[TestCase(typeof(KeyNotFoundException), true)]
|
||||
[TestCase(typeof(DivideByZeroException), true)]
|
||||
[TestCase(typeof(InvalidOperationException), true)]
|
||||
[TestCase(typeof(DllNotFoundException), false)]
|
||||
public void InterpretThrowsForNonDllNotFoundExceptionTypes(Type exceptionType, bool expectThrow)
|
||||
{
|
||||
var exception = CreateExceptionFromType(exceptionType);
|
||||
var interpreter = new DllNotFoundPythonExceptionInterpreter();
|
||||
var constraint = expectThrow ? (IResolveConstraint)Throws.Exception : Throws.Nothing;
|
||||
Assert.That(() => interpreter.Interpret(exception, NullExceptionInterpreter.Instance), constraint);
|
||||
}
|
||||
|
||||
private Exception CreateExceptionFromType(Type type)
|
||||
{
|
||||
if (type == typeof(DllNotFoundException))
|
||||
{
|
||||
return new DllNotFoundException("\'python3.6\'");
|
||||
}
|
||||
|
||||
return (Exception)Activator.CreateInstance(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using QuantConnect.Exceptions;
|
||||
|
||||
namespace QuantConnect.Tests.Common.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Provids a fake implementation that can be utilized in tests
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Keep it internal so it doesn't get picked up when loading all exception interpreters from assemblies
|
||||
/// </remarks>
|
||||
internal class FakeExceptionInterpreter : IExceptionInterpreter
|
||||
{
|
||||
private readonly int _order = 0;
|
||||
private readonly Func<Exception, bool> _canInterpret;
|
||||
private readonly Func<Exception, Exception> _interpret;
|
||||
|
||||
public int Order => _order;
|
||||
|
||||
public FakeExceptionInterpreter()
|
||||
{
|
||||
_canInterpret = e => true;
|
||||
|
||||
var count = 0;
|
||||
_interpret = e =>
|
||||
{
|
||||
if (e == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return new Exception($"Projected {++count}: " + e.Message, _interpret(e.InnerException));
|
||||
};
|
||||
}
|
||||
|
||||
public FakeExceptionInterpreter(Func<Exception, bool> canInterpret, Func<Exception, Exception> interpret, int order = 0)
|
||||
{
|
||||
_canInterpret = canInterpret;
|
||||
_interpret = interpret;
|
||||
_order = order;
|
||||
}
|
||||
|
||||
public bool CanInterpret(Exception exception)
|
||||
{
|
||||
return _canInterpret(exception);
|
||||
}
|
||||
|
||||
public Exception Interpret(Exception exception, IExceptionInterpreter innerInterpreter)
|
||||
{
|
||||
return _interpret(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Constraints;
|
||||
using Python.Runtime;
|
||||
using QuantConnect.Exceptions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Tests.Common.Exceptions
|
||||
{
|
||||
[TestFixture]
|
||||
public class InvalidTokenPythonExceptionInterpreterTests
|
||||
{
|
||||
private PythonException _pythonException;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
using (Py.GIL())
|
||||
{
|
||||
try
|
||||
{
|
||||
// importing a module with syntax error 'x = 01' will throw
|
||||
PyModule.FromString(Guid.NewGuid().ToString(), "x = 01");
|
||||
}
|
||||
catch (PythonException pythonException)
|
||||
{
|
||||
_pythonException = pythonException;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestCase(typeof(Exception), false)]
|
||||
[TestCase(typeof(KeyNotFoundException), false)]
|
||||
[TestCase(typeof(DivideByZeroException), false)]
|
||||
[TestCase(typeof(InvalidOperationException), false)]
|
||||
[TestCase(typeof(PythonException), true)]
|
||||
public void CanInterpretReturnsTrueForOnlyInvalidTokenPythonExceptionType(Type exceptionType, bool expectedResult)
|
||||
{
|
||||
var exception = CreateExceptionFromType(exceptionType);
|
||||
Assert.AreEqual(expectedResult, new InvalidTokenPythonExceptionInterpreter().CanInterpret(exception), $"Unexpected response for: {exception}");
|
||||
}
|
||||
|
||||
[TestCase(typeof(Exception), true)]
|
||||
[TestCase(typeof(KeyNotFoundException), true)]
|
||||
[TestCase(typeof(DivideByZeroException), true)]
|
||||
[TestCase(typeof(InvalidOperationException), true)]
|
||||
[TestCase(typeof(PythonException), false)]
|
||||
public void InterpretThrowsForNonInvalidTokenPythonExceptionTypes(Type exceptionType, bool expectThrow)
|
||||
{
|
||||
var exception = CreateExceptionFromType(exceptionType);
|
||||
var interpreter = new InvalidTokenPythonExceptionInterpreter();
|
||||
var constraint = expectThrow ? (IResolveConstraint)Throws.Exception : Throws.Nothing;
|
||||
Assert.That(() => interpreter.Interpret(exception, NullExceptionInterpreter.Instance), constraint);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VerifyMessageContainsStackTraceInformation()
|
||||
{
|
||||
var exception = CreateExceptionFromType(typeof(PythonException));
|
||||
var assembly = typeof(PythonExceptionInterpreter).Assembly;
|
||||
var interpreter = StackExceptionInterpreter.CreateFromAssemblies();
|
||||
exception = interpreter.Interpret(exception, NullExceptionInterpreter.Instance);
|
||||
Assert.True(exception.Message.Contains("x = 01"));
|
||||
}
|
||||
|
||||
private Exception CreateExceptionFromType(Type type) => type == typeof(PythonException) ? _pythonException : (Exception)Activator.CreateInstance(type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Constraints;
|
||||
using Python.Runtime;
|
||||
using QuantConnect.Exceptions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Tests.Common.Exceptions
|
||||
{
|
||||
[TestFixture]
|
||||
public class KeyErrorPythonExceptionInterpreterTests
|
||||
{
|
||||
private PythonException _pythonException;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
using (Py.GIL())
|
||||
{
|
||||
var module = Py.Import("Test_PythonExceptionInterpreter");
|
||||
dynamic algorithm = module.GetAttr("Test_PythonExceptionInterpreter").Invoke();
|
||||
|
||||
try
|
||||
{
|
||||
// dict()['SPY']
|
||||
algorithm.key_error();
|
||||
}
|
||||
catch (PythonException pythonException)
|
||||
{
|
||||
_pythonException = pythonException;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(typeof(Exception), ExpectedResult = false)]
|
||||
[TestCase(typeof(KeyNotFoundException), ExpectedResult = false)]
|
||||
[TestCase(typeof(DivideByZeroException), ExpectedResult = false)]
|
||||
[TestCase(typeof(InvalidOperationException), ExpectedResult = false)]
|
||||
[TestCase(typeof(PythonException), ExpectedResult = true)]
|
||||
public bool CanInterpretReturnsTrueForOnlyKeyErrorPythonExceptionType(Type exceptionType)
|
||||
{
|
||||
var exception = CreateExceptionFromType(exceptionType);
|
||||
return new KeyErrorPythonExceptionInterpreter().CanInterpret(exception);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(typeof(Exception), true)]
|
||||
[TestCase(typeof(KeyNotFoundException), true)]
|
||||
[TestCase(typeof(DivideByZeroException), true)]
|
||||
[TestCase(typeof(InvalidOperationException), true)]
|
||||
[TestCase(typeof(PythonException), false)]
|
||||
public void InterpretThrowsForNonKeyErrorPythonExceptionTypes(Type exceptionType, bool expectThrow)
|
||||
{
|
||||
var exception = CreateExceptionFromType(exceptionType);
|
||||
var interpreter = new KeyErrorPythonExceptionInterpreter();
|
||||
var constraint = expectThrow ? (IResolveConstraint)Throws.Exception : Throws.Nothing;
|
||||
Assert.That(() => interpreter.Interpret(exception, NullExceptionInterpreter.Instance), constraint);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VerifyMessageContainsStackTraceInformation()
|
||||
{
|
||||
var exception = CreateExceptionFromType(typeof(PythonException));
|
||||
var assembly = typeof(PythonExceptionInterpreter).Assembly;
|
||||
var interpreter = StackExceptionInterpreter.CreateFromAssemblies();
|
||||
exception = interpreter.Interpret(exception, NullExceptionInterpreter.Instance);
|
||||
Assert.True(exception.Message.Contains("dict()['SPY']"));
|
||||
}
|
||||
|
||||
private Exception CreateExceptionFromType(Type type) => type == typeof(PythonException) ? _pythonException : (Exception)Activator.CreateInstance(type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Constraints;
|
||||
using Python.Runtime;
|
||||
using QuantConnect.Exceptions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Tests.Common.Exceptions
|
||||
{
|
||||
[TestFixture]
|
||||
public class NoMethodMatchPythonExceptionInterpreterTests
|
||||
{
|
||||
private PythonException _pythonException;
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void Setup()
|
||||
{
|
||||
using (Py.GIL())
|
||||
{
|
||||
var module = Py.Import("Test_PythonExceptionInterpreter");
|
||||
dynamic algorithm = module.GetAttr("Test_PythonExceptionInterpreter").Invoke();
|
||||
|
||||
try
|
||||
{
|
||||
// self.SetCash('SPY')
|
||||
algorithm.no_method_match();
|
||||
}
|
||||
catch (PythonException pythonException)
|
||||
{
|
||||
_pythonException = pythonException;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(typeof(Exception), ExpectedResult = false)]
|
||||
[TestCase(typeof(KeyNotFoundException), ExpectedResult = false)]
|
||||
[TestCase(typeof(DivideByZeroException), ExpectedResult = false)]
|
||||
[TestCase(typeof(InvalidOperationException), ExpectedResult = false)]
|
||||
[TestCase(typeof(PythonException), ExpectedResult = true)]
|
||||
public bool CanInterpretReturnsTrueForOnlyNoMethodMatchPythonExceptionType(Type exceptionType)
|
||||
{
|
||||
var exception = CreateExceptionFromType(exceptionType);
|
||||
return new NoMethodMatchPythonExceptionInterpreter().CanInterpret(exception);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(typeof(Exception), true)]
|
||||
[TestCase(typeof(KeyNotFoundException), true)]
|
||||
[TestCase(typeof(DivideByZeroException), true)]
|
||||
[TestCase(typeof(InvalidOperationException), true)]
|
||||
[TestCase(typeof(PythonException), false)]
|
||||
public void InterpretThrowsForNonNoMethodMatchPythonExceptionTypes(Type exceptionType, bool expectThrow)
|
||||
{
|
||||
var exception = CreateExceptionFromType(exceptionType);
|
||||
var interpreter = new NoMethodMatchPythonExceptionInterpreter();
|
||||
var constraint = expectThrow ? (IResolveConstraint)Throws.Exception : Throws.Nothing;
|
||||
Assert.That(() => interpreter.Interpret(exception, NullExceptionInterpreter.Instance), constraint);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VerifyMessageContainsStackTraceInformation()
|
||||
{
|
||||
var exception = CreateExceptionFromType(typeof(PythonException));
|
||||
var assembly = typeof(PythonExceptionInterpreter).Assembly;
|
||||
var interpreter = StackExceptionInterpreter.CreateFromAssemblies();
|
||||
exception = interpreter.Interpret(exception, NullExceptionInterpreter.Instance);
|
||||
Assert.True(exception.Message.Contains("self.set_cash('SPY')"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VerifyMessageContainsTheMethodName()
|
||||
{
|
||||
var exception = CreateExceptionFromType(typeof(PythonException));
|
||||
var interpreter = new NoMethodMatchPythonExceptionInterpreter();
|
||||
exception = interpreter.Interpret(exception, NullExceptionInterpreter.Instance);
|
||||
|
||||
// The interpreter should reference the actual method name that failed to resolve
|
||||
// (set_cash, the snake_case name Python callers use), not a fragment of the argument
|
||||
// type list (e.g. "'str'>)").
|
||||
Assert.That(exception.Message, Does.Contain("set_cash"));
|
||||
Assert.That(exception.Message, Does.Not.Contain(">)"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VerifyMessageContainsTheMethodNameForOverloadedMethod()
|
||||
{
|
||||
PythonException pythonException;
|
||||
using (Py.GIL())
|
||||
{
|
||||
var module = Py.Import("Test_PythonExceptionInterpreter");
|
||||
dynamic algorithm = module.GetAttr("Test_PythonExceptionInterpreter").Invoke();
|
||||
|
||||
// self.rsi(symbol, 15, Resolution.DAILY) -- the third argument should be a
|
||||
// MovingAverageType, so no RSI overload matches the given arguments.
|
||||
pythonException = Assert.Throws<PythonException>(() => algorithm.no_method_match_rsi());
|
||||
}
|
||||
|
||||
var interpreter = new NoMethodMatchPythonExceptionInterpreter();
|
||||
var exception = interpreter.Interpret(pythonException, NullExceptionInterpreter.Instance);
|
||||
|
||||
// The interpreter should reference the rsi method name (snake_case, as Python callers
|
||||
// use it), not a fragment of the argument type list (e.g. "'QuantConnect.Resolution'>)").
|
||||
Assert.That(exception.Message, Does.Contain("rsi"));
|
||||
Assert.That(exception.Message, Does.Not.Contain(">)"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VerifyMessageKeepsTheOverloadsHint()
|
||||
{
|
||||
// pythonnet appends the candidate signatures to the binding-failure message.
|
||||
// set_cash('SPY') has multiple candidate overloads.
|
||||
var pythonException = (PythonException)CreateExceptionFromType(typeof(PythonException));
|
||||
StringAssert.Contains("The following overloads are available:", pythonException.Message);
|
||||
|
||||
var interpreter = new NoMethodMatchPythonExceptionInterpreter();
|
||||
var exception = interpreter.Interpret(pythonException, NullExceptionInterpreter.Instance);
|
||||
|
||||
// The interpreted message must keep the overloads hint so the user can see
|
||||
// what the method expects, not just that no overload matched.
|
||||
Assert.That(exception.Message, Does.Contain("The following overloads are available:"));
|
||||
Assert.That(exception.Message, Does.Contain("set_cash("));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VerifyMessageKeepsTheExpectedSignatureHint()
|
||||
{
|
||||
PythonException pythonException;
|
||||
using (Py.GIL())
|
||||
{
|
||||
var module = Py.Import("Test_PythonExceptionInterpreter");
|
||||
dynamic algorithm = module.GetAttr("Test_PythonExceptionInterpreter").Invoke();
|
||||
pythonException = Assert.Throws<PythonException>(() => algorithm.no_method_match_rsi());
|
||||
}
|
||||
|
||||
// rsi's candidate overloads collapse into a single snake-case signature,
|
||||
// so pythonnet words the hint as "The expected signature is:"
|
||||
StringAssert.Contains("The expected signature is:", pythonException.Message);
|
||||
|
||||
var interpreter = new NoMethodMatchPythonExceptionInterpreter();
|
||||
var exception = interpreter.Interpret(pythonException, NullExceptionInterpreter.Instance);
|
||||
|
||||
Assert.That(exception.Message, Does.Contain("The expected signature is:"));
|
||||
Assert.That(exception.Message, Does.Contain("rsi("));
|
||||
}
|
||||
|
||||
private Exception CreateExceptionFromType(Type type) => type == typeof(PythonException) ? _pythonException : (Exception)Activator.CreateInstance(type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using QuantConnect.Exceptions;
|
||||
|
||||
namespace QuantConnect.Tests.Common.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a null implementation of <see cref="IExceptionInterpreter"/>
|
||||
/// </summary>
|
||||
public class NullExceptionInterpreter : IExceptionInterpreter
|
||||
{
|
||||
public static readonly IExceptionInterpreter Instance = new NullExceptionInterpreter();
|
||||
|
||||
public int Order => int.MaxValue;
|
||||
|
||||
private NullExceptionInterpreter()
|
||||
{
|
||||
}
|
||||
|
||||
public bool CanInterpret(Exception exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public Exception Interpret(Exception exception, IExceptionInterpreter innerInterpreter)
|
||||
{
|
||||
return exception;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Constraints;
|
||||
using Python.Runtime;
|
||||
using QuantConnect.Exceptions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Tests.Common.Exceptions
|
||||
{
|
||||
[TestFixture]
|
||||
public class PythonExceptionInterpreterTests
|
||||
{
|
||||
private PythonException _pythonException;
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void Setup()
|
||||
{
|
||||
using (Py.GIL())
|
||||
{
|
||||
var module = Py.Import("Test_PythonExceptionInterpreter");
|
||||
dynamic algorithm = module.GetAttr("Test_PythonExceptionInterpreter").Invoke();
|
||||
|
||||
try
|
||||
{
|
||||
// x = 1 / 0
|
||||
algorithm.zero_division_error();
|
||||
}
|
||||
catch (PythonException pythonException)
|
||||
{
|
||||
_pythonException = pythonException;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(typeof(Exception), ExpectedResult = false)]
|
||||
[TestCase(typeof(KeyNotFoundException), ExpectedResult = false)]
|
||||
[TestCase(typeof(DivideByZeroException), ExpectedResult = false)]
|
||||
[TestCase(typeof(InvalidOperationException), ExpectedResult = false)]
|
||||
[TestCase(typeof(PythonException), ExpectedResult = true)]
|
||||
public bool CanInterpretReturnsTrueForOnlyPythonExceptionType(Type exceptionType)
|
||||
{
|
||||
var exception = CreateExceptionFromType(exceptionType);
|
||||
return new PythonExceptionInterpreter().CanInterpret(exception);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(typeof(Exception), true)]
|
||||
[TestCase(typeof(KeyNotFoundException), true)]
|
||||
[TestCase(typeof(DivideByZeroException), true)]
|
||||
[TestCase(typeof(InvalidOperationException), true)]
|
||||
[TestCase(typeof(PythonException), false)]
|
||||
public void InterpretThrowsForNonPythonExceptionTypes(Type exceptionType, bool expectThrow)
|
||||
{
|
||||
var exception = CreateExceptionFromType(exceptionType);
|
||||
var interpreter = new PythonExceptionInterpreter();
|
||||
var constraint = expectThrow ? (IResolveConstraint)Throws.Exception : Throws.Nothing;
|
||||
Assert.That(() => interpreter.Interpret(exception, NullExceptionInterpreter.Instance), constraint);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VerifyMessageContainsStackTraceInformation()
|
||||
{
|
||||
var exception = CreateExceptionFromType(typeof(PythonException));
|
||||
var assembly = typeof(PythonExceptionInterpreter).Assembly;
|
||||
var interpreter = StackExceptionInterpreter.CreateFromAssemblies();
|
||||
exception = interpreter.Interpret(exception, NullExceptionInterpreter.Instance);
|
||||
Assert.True(exception.Message.Contains("x = 1 / 0"));
|
||||
}
|
||||
|
||||
private Exception CreateExceptionFromType(Type type) => type == typeof(PythonException) ? _pythonException : (Exception)Activator.CreateInstance(type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Constraints;
|
||||
using QuantConnect.Exceptions;
|
||||
using QuantConnect.Scheduling;
|
||||
|
||||
namespace QuantConnect.Tests.Common.Exceptions
|
||||
{
|
||||
[TestFixture]
|
||||
public class ScheduledEventExceptionInterpreterTests
|
||||
{
|
||||
[Test]
|
||||
[TestCase(typeof(Exception), ExpectedResult = false)]
|
||||
[TestCase(typeof(KeyNotFoundException), ExpectedResult = false)]
|
||||
[TestCase(typeof(DivideByZeroException), ExpectedResult = false)]
|
||||
[TestCase(typeof(InvalidOperationException), ExpectedResult = false)]
|
||||
[TestCase(typeof(ScheduledEventException), ExpectedResult = true)]
|
||||
public bool CanProjectReturnsTrueForOnlyScheduledEventExceptionType(Type exceptionType)
|
||||
{
|
||||
var exception = CreateExceptionFromType(exceptionType);
|
||||
return new ScheduledEventExceptionInterpreter().CanInterpret(exception);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(typeof(Exception), true)]
|
||||
[TestCase(typeof(KeyNotFoundException), true)]
|
||||
[TestCase(typeof(DivideByZeroException), true)]
|
||||
[TestCase(typeof(InvalidOperationException), true)]
|
||||
[TestCase(typeof(ScheduledEventException), false)]
|
||||
public void ProjectThrowsForNonScheduledEventExceptionTypes(Type exceptionType, bool expectThrow)
|
||||
{
|
||||
var exception = CreateExceptionFromType(exceptionType);
|
||||
var interpreter = new ScheduledEventExceptionInterpreter();
|
||||
var constraint = expectThrow ? (IResolveConstraint)Throws.Exception : Throws.Nothing;
|
||||
Assert.That(() => interpreter.Interpret(exception, NullExceptionInterpreter.Instance), constraint);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReformsMessageToIncludeScheduledEventName()
|
||||
{
|
||||
var id = Guid.NewGuid();
|
||||
var name = id.ToStringInvariant("D");
|
||||
var message = id.ToStringInvariant("N");
|
||||
var exception = new ScheduledEventException(name, message, null);
|
||||
var interpreted = new ScheduledEventExceptionInterpreter().Interpret(exception, NullExceptionInterpreter.Instance);
|
||||
|
||||
var expectedInterpretedMessage = $"In Scheduled Event '{name}',";
|
||||
Assert.AreEqual(expectedInterpretedMessage, interpreted.Message);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WrapsScheduledEventExceptionInnerException()
|
||||
{
|
||||
var inner = new Exception();
|
||||
var exception = new ScheduledEventException("name", "message", inner);
|
||||
var interpreted = new ScheduledEventExceptionInterpreter().Interpret(exception, NullExceptionInterpreter.Instance);
|
||||
Assert.AreEqual(inner, interpreted.InnerException);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InvokesInnerExceptionProjectionOnInnerException()
|
||||
{
|
||||
var inner = new Exception("inner");
|
||||
var exception = new ScheduledEventException("name", "message", inner);
|
||||
var mockInnerInterpreter = new Mock<IExceptionInterpreter>();
|
||||
mockInnerInterpreter.Setup(iep => iep.Interpret(inner, mockInnerInterpreter.Object))
|
||||
.Returns(new Exception("Projected " + inner.Message))
|
||||
.Verifiable();
|
||||
|
||||
var interpreter = new ScheduledEventExceptionInterpreter();
|
||||
|
||||
interpreter.Interpret(exception, mockInnerInterpreter.Object);
|
||||
|
||||
mockInnerInterpreter.Verify(iep => iep.Interpret(inner, mockInnerInterpreter.Object), Times.Exactly(1));
|
||||
}
|
||||
|
||||
private Exception CreateExceptionFromType(Type type)
|
||||
{
|
||||
if (type == typeof(ScheduledEventException))
|
||||
{
|
||||
var inner = new Exception("Sample inner message");
|
||||
return new ScheduledEventException(Guid.NewGuid().ToStringInvariant(null), "Sample error message", inner);
|
||||
}
|
||||
|
||||
return (Exception)Activator.CreateInstance(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using QuantConnect.Exceptions;
|
||||
|
||||
namespace QuantConnect.Tests.Common.Exceptions
|
||||
{
|
||||
[TestFixture]
|
||||
public class StackExceptionInterpretersTests
|
||||
{
|
||||
[Test]
|
||||
public void CreatesFromAssemblies()
|
||||
{
|
||||
var assembly = typeof(ClrBubbledExceptionInterpreter).Assembly;
|
||||
var interpreter = StackExceptionInterpreter.CreateFromAssemblies();
|
||||
Assert.AreEqual(1, interpreter.Interpreters.Count(p => p.GetType() == typeof(ClrBubbledExceptionInterpreter)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CallsInterpretOnFirstProjectionThatCanInterpret()
|
||||
{
|
||||
var canInterpretCalled = new List<int>();
|
||||
var interpretCalled = new List<int>();
|
||||
var interpreters = new[]
|
||||
{
|
||||
new FakeExceptionInterpreter(e =>
|
||||
{
|
||||
canInterpretCalled.Add(0);
|
||||
return false;
|
||||
}, e =>
|
||||
{
|
||||
interpretCalled.Add(0);
|
||||
return e;
|
||||
},
|
||||
order : 2),
|
||||
new FakeExceptionInterpreter(e =>
|
||||
{
|
||||
canInterpretCalled.Add(1);
|
||||
return true;
|
||||
}, e =>
|
||||
{
|
||||
interpretCalled.Add(1);
|
||||
return e;
|
||||
},
|
||||
order : 1),
|
||||
new FakeExceptionInterpreter(e =>
|
||||
{
|
||||
canInterpretCalled.Add(2);
|
||||
return false;
|
||||
}, e =>
|
||||
{
|
||||
interpretCalled.Add(2);
|
||||
return e;
|
||||
},
|
||||
order : 0)
|
||||
};
|
||||
|
||||
var interpreter = new StackExceptionInterpreter(interpreters);
|
||||
interpreter.Interpret(new Exception(), null);
|
||||
|
||||
// can interpret called for 3nd and 2rd entry
|
||||
Assert.Contains(2, canInterpretCalled);
|
||||
Assert.Contains(1, canInterpretCalled);
|
||||
Assert.That(canInterpretCalled, Is.Not.Contains(0));
|
||||
|
||||
// interpret only called on second entry
|
||||
Assert.That(interpretCalled, Is.Not.Contains(0));
|
||||
Assert.Contains(1, interpretCalled);
|
||||
Assert.That(interpretCalled, Is.Not.Contains(2));
|
||||
|
||||
// interpreter called 3rd before 2nd
|
||||
Assert.Greater(canInterpretCalled.First(), canInterpretCalled.Last());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RecursivelyProjectsInnerExceptions()
|
||||
{
|
||||
var inner = new Exception("inner");
|
||||
var middle = new Exception("middle", inner);
|
||||
var outter = new Exception("outter", middle);
|
||||
var interpreter = new StackExceptionInterpreter(new[]
|
||||
{
|
||||
new FakeExceptionInterpreter()
|
||||
});
|
||||
|
||||
var interpreted = interpreter.Interpret(outter, null);
|
||||
Assert.AreEqual("Projected 1: outter", interpreted.Message);
|
||||
Assert.AreEqual("Projected 2: middle", interpreted.InnerException.Message);
|
||||
Assert.AreEqual("Projected 3: inner", interpreted.InnerException.InnerException.Message);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetsExceptionMessageHeaderAsAllInnersJoinedBySpace()
|
||||
{
|
||||
var inner = new Exception("inner");
|
||||
var middle = new Exception("middle", inner);
|
||||
var outter = new Exception("outter", middle);
|
||||
var message = new StackExceptionInterpreter(Enumerable.Empty<IExceptionInterpreter>()).GetExceptionMessageHeader(outter);
|
||||
|
||||
// header line w/ exception message and then the full detail on a new line
|
||||
var expectedMessage = "outter middle inner";
|
||||
Assert.AreEqual(expectedMessage, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using QuantConnect.Exceptions;
|
||||
using QuantConnect.Logging;
|
||||
|
||||
namespace QuantConnect.Tests.Common.Exceptions
|
||||
{
|
||||
[TestFixture]
|
||||
public class SystemExceptionInterpreterTests
|
||||
{
|
||||
[Test]
|
||||
public void InterpreterCorrectly()
|
||||
{
|
||||
var result = SystemExceptionInterpreter.TryGetLineAndFile(@" at QuantConnect.Algorithm.CSharp.BasicTemplateAlgorithm.Initialize() in D:\QuantConnect\MyLean\Lean\Algorithm.CSharp\BasicTemplateAlgorithm.cs:line 50
|
||||
at QuantConnect.Lean.Engine.Setup.BacktestingSetupHandler.<>c__DisplayClass27_0.<Setup>b__0() in D:\QuantConnect\MyLean\Lean\Engine\Setup\BacktestingSetupHandler.cs:line 186
|
||||
", out var fileAndLine);
|
||||
|
||||
Assert.IsTrue(result);
|
||||
Assert.AreEqual(" in BasicTemplateAlgorithm.cs:line 50", fileAndLine);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CleanupStacktrace()
|
||||
{
|
||||
var interpreter = new SystemExceptionInterpreter();
|
||||
|
||||
var message = "The ticker AAPL was not found in the SymbolCache. Use the Symbol object as key instead. Accessing the securities collection/slice object by string ticker is only available for" +
|
||||
" securities added with the AddSecurity-family methods. For more details, please check out the documentation.";
|
||||
var stackTrace = " at QuantConnect.ExtendedDictionary`1.get_Item(String ticker) in D:\\QuantConnect\\MyLean\\Lean\\Common\\ExtendedDictionary.cs:line 121\r\n at QuantConnect.Algorithm.CSh" +
|
||||
"arp.BasicTemplateAlgorithm.OnData(Slice data) in D:\\QuantConnect\\MyLean\\Lean\\Algorithm.CSharp\\BasicTemplateAlgorithm.cs:line 58\r\n at QuantConnect.Lean.Engine.AlgorithmManager.R" +
|
||||
"un(AlgorithmNodePacket job, IAlgorithm algorithm, ISynchronizer synchronizer, ITransactionHandler transactions, IResultHandler results, IRealTimeHandler realtime, ILeanManager leanMana" +
|
||||
"ger, CancellationToken token) in D:\\QuantConnect\\MyLean\\Lean\\Engine\\AlgorithmManager.cs:line 525";
|
||||
var result = interpreter.Interpret(new TestException(message, stackTrace), null);
|
||||
|
||||
Assert.AreEqual(" at QuantConnect.ExtendedDictionary`1.get_Item(String ticker) in Common\\ExtendedDictionary.cs:line 121\r\n at QuantConnect.Algorithm.CSharp.BasicTemplateAlgorithm.OnData(" +
|
||||
"Slice data) in Algorithm.CSharp\\BasicTemplateAlgorithm.cs:line 58\r\n at QuantConnect.Lean.Engine.AlgorithmManager.Run(AlgorithmNodePacket job, IAlgorithm algorithm, ISynchronizer sync" +
|
||||
"hronizer, ITransactionHandler transactions, IResultHandler results, IRealTimeHandler realtime, ILeanManager leanManager, CancellationToken token) in Engine\\AlgorithmManager.cs:line 525", result.InnerException.StackTrace);
|
||||
}
|
||||
|
||||
[TestCase("")]
|
||||
[TestCase(null)]
|
||||
public void CleanupStackTraceHandles(string stackTrace)
|
||||
{
|
||||
var interpreter = new SystemExceptionInterpreter();
|
||||
var result = interpreter.Interpret(new TestException("Message", stackTrace), null);
|
||||
|
||||
Assert.IsNull(result.InnerException);
|
||||
}
|
||||
|
||||
private class TestException : Exception
|
||||
{
|
||||
private readonly string _message;
|
||||
private readonly string _stackTrace;
|
||||
|
||||
public override string Message => _message;
|
||||
public override string StackTrace => _stackTrace;
|
||||
|
||||
public TestException(string message, string stackTrace)
|
||||
{
|
||||
_message = message;
|
||||
_stackTrace = Log.ClearLeanPaths(stackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
|
||||
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Constraints;
|
||||
using Python.Runtime;
|
||||
using QuantConnect.Exceptions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuantConnect.Tests.Common.Exceptions
|
||||
{
|
||||
[TestFixture]
|
||||
public class UnsupportedOperandPythonExceptionInterpreterTests
|
||||
{
|
||||
private PythonException _pythonException;
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void Setup()
|
||||
{
|
||||
using (Py.GIL())
|
||||
{
|
||||
var module = Py.Import("Test_PythonExceptionInterpreter");
|
||||
dynamic algorithm = module.GetAttr("Test_PythonExceptionInterpreter").Invoke();
|
||||
|
||||
try
|
||||
{
|
||||
// x = None + "Pepe Grillo"
|
||||
algorithm.unsupported_operand();
|
||||
}
|
||||
catch (PythonException pythonException)
|
||||
{
|
||||
_pythonException = pythonException;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(typeof(Exception), ExpectedResult = false)]
|
||||
[TestCase(typeof(KeyNotFoundException), ExpectedResult = false)]
|
||||
[TestCase(typeof(DivideByZeroException), ExpectedResult = false)]
|
||||
[TestCase(typeof(InvalidOperationException), ExpectedResult = false)]
|
||||
[TestCase(typeof(PythonException), ExpectedResult = true)]
|
||||
public bool CanInterpretReturnsTrueForOnlyUnsupportedOperandPythonExceptionType(Type exceptionType)
|
||||
{
|
||||
var exception = CreateExceptionFromType(exceptionType);
|
||||
return new UnsupportedOperandPythonExceptionInterpreter().CanInterpret(exception);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(typeof(Exception), true)]
|
||||
[TestCase(typeof(KeyNotFoundException), true)]
|
||||
[TestCase(typeof(DivideByZeroException), true)]
|
||||
[TestCase(typeof(InvalidOperationException), true)]
|
||||
[TestCase(typeof(PythonException), false)]
|
||||
public void InterpretThrowsForNonUnsupportedOperandPythonExceptionTypes(Type exceptionType, bool expectThrow)
|
||||
{
|
||||
var exception = CreateExceptionFromType(exceptionType);
|
||||
var interpreter = new UnsupportedOperandPythonExceptionInterpreter();
|
||||
var constraint = expectThrow ? (IResolveConstraint)Throws.Exception : Throws.Nothing;
|
||||
Assert.That(() => interpreter.Interpret(exception, NullExceptionInterpreter.Instance), constraint);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void VerifyMessageContainsStackTraceInformation()
|
||||
{
|
||||
var exception = CreateExceptionFromType(typeof(PythonException));
|
||||
var assembly = typeof(PythonExceptionInterpreter).Assembly;
|
||||
var interpreter = StackExceptionInterpreter.CreateFromAssemblies();
|
||||
exception = interpreter.Interpret(exception, NullExceptionInterpreter.Instance);
|
||||
Assert.True(exception.Message.Contains("x = None + \"Pepe Grillo\""));
|
||||
}
|
||||
|
||||
private Exception CreateExceptionFromType(Type type) => type == typeof(PythonException) ? _pythonException : (Exception)Activator.CreateInstance(type);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user