Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When using pipe and testing for exception "raises" finds reflection exception instead #63

Closed
GoogleCodeExporter opened this issue Jun 21, 2015 · 2 comments

Comments

@GoogleCodeExporter
Copy link

What steps will reproduce the problem?

                 member this.RaiseException(message:string)=
                        raise (NotSupportedException(message))

        [<Test>] member this.``Bad Unquote Returning it's own reflection exception`` ()=
                        raises<NotSupportedException> <@ "Should be a NotSupportedException" |> this.RaiseException  @>


What is the expected output? 
the Test passing.

What do you see instead?

Expected NotSupportedException but got TargetInvocationException

"Should be a NotSupportedException" |> UnitTest.FSharp.Tests.Module1+Basic 
Dynamic Operator Tests.RaiseException
System.Reflection.TargetInvocationException: Exception has been thrown by the 
target of an invocation. ---> System.NotSupportedException: Should be a 
NotSupportedException
   at UnitTest.FSharp.Tests.Module1.TestCase Dynamic Operator Tests.RaiseException[a](String message) in C:\Documents and Settings\username\My Documents\Visual Studio 2010\Projects\testproject\UnitTest.FSharp\TestCase.fs:line 30
   --- End of inner exception stack trace ---

Server stack trace: 
   at System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
   at System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at <StartupCode$FSharp-Core>.$Reflect.Invoke@617-4.Invoke(T1 inp)

Exception rethrown at [0]: 
   at Swensen.Unquote.Evaluation.eval(FSharpMap`2 env, FSharpExpr expr)
   at Swensen.Unquote.Reduction.reduce(FSharpMap`2 env, FSharpExpr expr)
   at Swensen.Unquote.Reduction.loop@119(FSharpMap`2 env, FSharpExpr expr, FSharpList`1 acc)

What version of the product are you using? On what operating system?

Unquote.2.0.2

Please provide any additional information below.


Original issue reported on code.google.com by tech.ekon.us on 3 Aug 2011 at 2:23

@GoogleCodeExporter
Copy link
Author

Thank you for reporting this very interesting and very important bug!

While Unquote did take measures to strip outermost reflective 
TargetInvocationExceptions, it did not account for a unique case in F# where 
there may be nested TargetInvocationExceptions. 

The case is this: sometimes when core operators such as raises are invoked from 
assemblies which are not compiled by F# (such as through the .NET reflection 
assemblies, an implementation detail of Unquote's quotation evaluator), the 
operators themselves are exposed as reflective calls, so in the case of this 
bug we get to levels of reflective calls and therefore two nested 
TargetInvocationExceptions.

This issue has been fixed in trunk and will be available in a new release very 
soon.

Note that stripping nested TargetInvocationExceptions in this way forces us 
into a compromise: we effectively cannot test for 
raises<TargetInvocationException> because we can't always tell whether the 
intention is to preserve or strip those reflective exceptions.

While fixing this issue I also decided to use a different strategy for 
preserving stacktraces when extracting inner exceptions from (possibly nested) 
TargetInvocationExceptions. Instead of using the PrepForRemoting() non-public 
method on the exception, which in addition to preserving the stack trace also 
produces a verbose message as you've seen, I am now using a strategy which only 
preserves the stack trace and uses the original message. I think this is closer 
to what folks would expect if F# provided native "eval", reflection is just an 
implementation detail.

Original comment by stephen....@gmail.com on 6 Aug 2011 at 3:18

  • Changed state: Fixed
  • Added labels: Priority-High
  • Removed labels: Priority-Medium

@GoogleCodeExporter
Copy link
Author

Original comment by stephen....@gmail.com on 7 Aug 2011 at 6:04

  • Added labels: Milestone-Release2.0.3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant