1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System.Collections.Generic;
6 using System.Globalization;
7 using System.Linq;
8 using Xunit;
9 
10 namespace System.Reflection.Tests
11 {
12     public static class BindingFlagsDoNotWrapTests
13     {
14         [Fact]
MethodInvoke()15         public static void MethodInvoke()
16         {
17             MethodInfo m = typeof(TestClass).GetMethod(nameof(TestClass.Moo), BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);
18             TestDoNotWrap<MyException1>((bf) => m.Invoke(null, bf, null, Array.Empty<object>(), null));
19         }
20 
21         [Fact]
ConstructorInvoke()22         public static void ConstructorInvoke()
23         {
24             ConstructorInfo c = typeof(TestClass).GetConstructor(BindingFlags.Public|BindingFlags.Instance, null, Array.Empty<Type>(), null);
25             TestDoNotWrap<MyException2>((bf) => c.Invoke(bf, null, Array.Empty<object>(), null));
26         }
27 
28         [Fact]
ConstructorInvokeStringCtor()29         public static void ConstructorInvokeStringCtor()
30         {
31             // Code coverage: Project N - String constructors go through a separate code path.
32             ConstructorInfo c = typeof(string).GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(char[]), typeof(int), typeof(int) }, null);
33             TestDoNotWrap<ArgumentNullException>((bf) => c.Invoke(bf, null, new object[] { null, 0, 0 }, null));
34         }
35 
36         [Fact]
ConstructorInvokeUsingMethodInfoInvoke()37         public static void ConstructorInvokeUsingMethodInfoInvoke()
38         {
39             ConstructorInfo c = typeof(TestClass).GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, Array.Empty<Type>(), null);
40             TestDoNotWrap<MyException2>((bf) => c.Invoke(new TestClass(0), bf, null, Array.Empty<object>(), null));
41         }
42 
43         [Fact]
PropertyGet()44         public static void PropertyGet()
45         {
46             PropertyInfo p = typeof(TestClass).GetProperty(nameof(TestClass.MyProperty));
47             TestDoNotWrap<MyException3>((bf) => p.GetValue(null, bf, null, null, null));
48         }
49 
50         [Fact]
PropertySet()51         public static void PropertySet()
52         {
53             PropertyInfo p = typeof(TestClass).GetProperty(nameof(TestClass.MyProperty));
54             TestDoNotWrap<MyException4>((bf) => p.SetValue(null, 42, bf, null, null, null));
55         }
56 
57         [Fact]
InvokeMember_Method()58         public static void InvokeMember_Method()
59         {
60             Type t = typeof(TestClass);
61             const BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.InvokeMethod;
62             TestDoNotWrap<MyException1>((bf) => t.InvokeMember(nameof(TestClass.Moo), bf | flags, null, null, Array.Empty<object>(), null, null, null));
63         }
64 
65         [Fact]
InvokeMember_PropertyGet()66         public static void InvokeMember_PropertyGet()
67         {
68             Type t = typeof(TestClass);
69             const BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.GetProperty;
70             TestDoNotWrap<MyException3>((bf) => t.InvokeMember(nameof(TestClass.MyProperty), bf | flags, null, null, Array.Empty<object>(), null, null, null));
71         }
72 
73         [Fact]
InvokeMember_PropertySet()74         public static void InvokeMember_PropertySet()
75         {
76             Type t = typeof(TestClass);
77             const BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.SetProperty;
78             TestDoNotWrap<MyException4>((bf) => t.InvokeMember(nameof(TestClass.MyProperty), bf | flags, null, null, new object[] { 42 }, null, null, null));
79         }
80 
81         [Fact]
ActivatorCreateInstance()82         public static void ActivatorCreateInstance()
83         {
84             const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
85             TestDoNotWrap<MyException2>((bf) => Activator.CreateInstance(typeof(TestClass), bf | flags, null, Array.Empty<object>(), null, null));
86         }
87 
88         [Fact]
ActivatorCreateInstanceOneArgument()89         public static void ActivatorCreateInstanceOneArgument()
90         {
91             // For code coverage on CoreCLR: Activator.CreateInstance with parameters uses different code path from one without parameters.
92             const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
93             TestDoNotWrap<MyException5>((bf) => Activator.CreateInstance(typeof(TestClass), bf | flags, null, new object[] { "Hello" }, null, null));
94         }
95 
96         [Fact]
ActivatorCreateInstanceCaching()97         public static void ActivatorCreateInstanceCaching()
98         {
99             // For code coverage on CoreCLR: Activator.CreateInstance - second call after non-throwing call goes through a different path
100             const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
101             TestClassConditional.ThrowInConstructor = true;
102             TestDoNotWrap<MyException6>((bf) => Activator.CreateInstance(typeof(TestClassConditional), bf | flags, null, Array.Empty<object>(), null, null));
103 
104             TestClassConditional.ThrowInConstructor = false;
105             Assert.True(Activator.CreateInstance(typeof(TestClassConditional), flags, null, Array.Empty<object>(), null, null) is TestClassConditional);
106 
107             TestClassConditional.ThrowInConstructor = true;
108             TestDoNotWrap<MyException6>((bf) => Activator.CreateInstance(typeof(TestClassConditional), bf | flags, null, Array.Empty<object>(), null, null));
109         }
110 
111         [Fact]
ActivatorCreateInstance_BadCCtor()112         public static void ActivatorCreateInstance_BadCCtor()
113         {
114             const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
115             TestDoNotWrap<TypeInitializationException>((bf) => Activator.CreateInstance(typeof(TestClassBadCCtor), bf | flags, null, Array.Empty<object>(), null, null));
116         }
117 
118         [Fact]
AssemblyCreateInstance()119         public static void AssemblyCreateInstance()
120         {
121             Assembly a = typeof(TestClass).Assembly;
122             const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
123             TestDoNotWrap<MyException2>((bf) => a.CreateInstance(typeof(TestClass).FullName, false, bf | flags, null, Array.Empty<object>(), null, null));
124         }
125 
126         [Fact]
AssemblyCreateInstance_BadCCtor()127         public static void AssemblyCreateInstance_BadCCtor()
128         {
129             Assembly a = typeof(TestClass).Assembly;
130             const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
131             TestDoNotWrap<TypeInitializationException>((bf) => a.CreateInstance(typeof(TestClassBadCCtor).FullName, false, bf | flags, null, Array.Empty<object>(), null, null));
132         }
133 
134         private static void TestDoNotWrap<T>(Action<BindingFlags> action) where T : Exception
135         {
136             Assert.Throws<T>(() => action(BindingFlags.DoNotWrapExceptions));
137             TargetInvocationException tie = Assert.Throws<TargetInvocationException>(() => action(default(BindingFlags)));
138             Assert.Equal(typeof(T), tie.InnerException.GetType());
139         }
140 
141         private sealed class TestClass
142         {
TestClass()143             public TestClass() => throw new MyException2();
TestClass(int _)144             public TestClass(int _) { }
TestClass(string s)145             public TestClass(string s) => throw new MyException5();
Moo()146             public static void Moo() => throw new MyException1();
147             public static int MyProperty { get { throw new MyException3(); } set { throw new MyException4(); } }
148         }
149 
150         public sealed class TestClassBadCCtor
151         {
TestClassBadCCtor()152             public TestClassBadCCtor() { }
153 
TestClassBadCCtor()154             static TestClassBadCCtor()
155             {
156                 throw new MyException1();
157             }
158         }
159 
160         private sealed class TestClassConditional
161         {
TestClassConditional()162             public TestClassConditional() { if (ThrowInConstructor) throw new MyException6(); }
163 
164             public static bool ThrowInConstructor;
165         }
166 
167         private sealed class MyException1 : Exception { }
168         private sealed class MyException2 : Exception { }
169         private sealed class MyException3 : Exception { }
170         private sealed class MyException4 : Exception { }
171         private sealed class MyException5 : Exception { }
172         private sealed class MyException6 : Exception { }
173     }
174 }
175