DynamicMethodTest.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794
  1. //
  2. // DynamicMethodTest.cs - NUnit Test Cases for the DynamicMethod class
  3. //
  4. // Gert Driesen ([email protected])
  5. // Konrad Kruczynski
  6. //
  7. // (C) 2006 Novell
  8. using System;
  9. using System.Reflection;
  10. using System.Reflection.Emit;
  11. using System.Runtime.InteropServices;
  12. using System.Runtime.CompilerServices;
  13. using System.Text;
  14. using System.Diagnostics;
  15. using System.Runtime.ExceptionServices;
  16. using System.Linq;
  17. using NUnit.Framework;
  18. namespace MonoTests.System.Reflection.Emit
  19. {
  20. [TestFixture]
  21. public class DynamicMethodTest
  22. {
  23. private delegate int HelloInvoker (string msg);
  24. [Test]
  25. public void Constructor1_Name_Null ()
  26. {
  27. try {
  28. new DynamicMethod (null,
  29. typeof (void),
  30. new Type[] { typeof (string) },
  31. typeof (DynamicMethodTest).Module);
  32. Assert.Fail ("#1");
  33. } catch (ArgumentNullException ex) {
  34. Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
  35. Assert.AreEqual ("name", ex.ParamName, "#3");
  36. Assert.IsNull (ex.InnerException, "#4");
  37. }
  38. }
  39. [Test]
  40. public void Constructor2_Name_Null ()
  41. {
  42. try {
  43. new DynamicMethod (null,
  44. typeof (void),
  45. new Type[] { typeof (string) },
  46. typeof (DynamicMethodTest));
  47. Assert.Fail ("#1");
  48. } catch (ArgumentNullException ex) {
  49. Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
  50. Assert.AreEqual ("name", ex.ParamName, "#3");
  51. Assert.IsNull (ex.InnerException, "#4");
  52. }
  53. }
  54. [Test]
  55. public void Constructor3_Name_Null ()
  56. {
  57. try {
  58. new DynamicMethod (null,
  59. typeof (void),
  60. new Type[] { typeof (string) },
  61. typeof (DynamicMethodTest).Module, true);
  62. Assert.Fail ("#1");
  63. } catch (ArgumentNullException ex) {
  64. Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
  65. Assert.AreEqual ("name", ex.ParamName, "#3");
  66. Assert.IsNull (ex.InnerException, "#4");
  67. }
  68. }
  69. [Test]
  70. public void Constructor4_Name_Null ()
  71. {
  72. try {
  73. new DynamicMethod (null,
  74. typeof (void),
  75. new Type[] { typeof (string) },
  76. typeof (DynamicMethodTest), true);
  77. Assert.Fail ("#1");
  78. } catch (ArgumentNullException ex) {
  79. Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
  80. Assert.AreEqual ("name", ex.ParamName, "#3");
  81. Assert.IsNull (ex.InnerException, "#4");
  82. }
  83. }
  84. [Test]
  85. public void Constructor5_Name_Null ()
  86. {
  87. try {
  88. new DynamicMethod (null,
  89. MethodAttributes.Public | MethodAttributes.Static,
  90. CallingConventions.Standard,
  91. typeof (void),
  92. new Type[] { typeof (string) },
  93. typeof (DynamicMethodTest).Module, true);
  94. Assert.Fail ("#1");
  95. } catch (ArgumentNullException ex) {
  96. Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
  97. Assert.AreEqual ("name", ex.ParamName, "#3");
  98. Assert.IsNull (ex.InnerException, "#4");
  99. }
  100. }
  101. [Test]
  102. public void Constructor6_Name_Null ()
  103. {
  104. try {
  105. new DynamicMethod (null,
  106. MethodAttributes.Public | MethodAttributes.Static,
  107. CallingConventions.Standard,
  108. typeof (void),
  109. new Type[] { typeof (string) },
  110. typeof (DynamicMethodTest), true);
  111. Assert.Fail ("#1");
  112. } catch (ArgumentNullException ex) {
  113. Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
  114. Assert.AreEqual ("name", ex.ParamName, "#3");
  115. Assert.IsNull (ex.InnerException, "#4");
  116. }
  117. }
  118. [Test]
  119. public void OwnerCantBeArray ()
  120. {
  121. TestOwner (typeof (int[]));
  122. }
  123. [Test]
  124. public void OwnerCantBeInterface ()
  125. {
  126. TestOwner (typeof (global::System.Collections.IEnumerable));
  127. }
  128. private void TestOwner (Type owner)
  129. {
  130. try {
  131. new DynamicMethod ("Name", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard,
  132. typeof(void), new Type[] { }, owner, true);
  133. Assert.Fail (string.Format ("Created dynamic method with owner being {0}.", owner));
  134. } catch (ArgumentException) {
  135. }
  136. }
  137. [Test] // bug #78253
  138. public void DynamicMethodReference ()
  139. {
  140. DynamicMethod hello = new DynamicMethod ("Hello",
  141. typeof (int),
  142. new Type[] { typeof (string) },
  143. typeof (DynamicMethodTest).Module);
  144. Assert.IsNull (hello.DeclaringType, "#1");
  145. DynamicMethod write = new DynamicMethod ("Write",
  146. typeof (int),
  147. new Type[] { typeof (string) },
  148. typeof (DynamicMethodTest));
  149. Assert.IsNull (hello.DeclaringType, "#2");
  150. MethodInfo invokeWrite = write.GetBaseDefinition ();
  151. ILGenerator helloIL = hello.GetILGenerator ();
  152. helloIL.Emit (OpCodes.Ldarg_0);
  153. helloIL.EmitCall (OpCodes.Call, invokeWrite, null);
  154. helloIL.Emit (OpCodes.Ret);
  155. ILGenerator writeIL = write.GetILGenerator ();
  156. writeIL.Emit (OpCodes.Ldc_I4_2);
  157. writeIL.Emit (OpCodes.Ret);
  158. HelloInvoker hi =
  159. (HelloInvoker) hello.CreateDelegate (typeof (HelloInvoker));
  160. int ret = hi ("Hello, World!");
  161. Assert.AreEqual (2, ret, "#3");
  162. object[] invokeArgs = { "Hello, World!" };
  163. object objRet = hello.Invoke (null, invokeArgs);
  164. Assert.AreEqual (2, objRet, "#4");
  165. }
  166. [Test]
  167. public void EmptyMethodBody ()
  168. {
  169. DynamicMethod hello = new DynamicMethod ("Hello",
  170. typeof (int),
  171. new Type[] { typeof (string) },
  172. typeof (DynamicMethodTest).Module);
  173. object[] invokeArgs = { "Hello, World!" };
  174. // no IL generator
  175. try {
  176. hello.Invoke (null, invokeArgs);
  177. Assert.Fail ("#1");
  178. } catch (InvalidOperationException) {
  179. }
  180. // empty method body
  181. hello.GetILGenerator ();
  182. try {
  183. hello.Invoke (null, invokeArgs);
  184. Assert.Fail ("#2");
  185. } catch (InvalidOperationException) {
  186. }
  187. }
  188. private delegate string ReturnString (string msg);
  189. private delegate void DoNothing (string msg);
  190. private static string private_method (string s) {
  191. return s;
  192. }
  193. [Test]
  194. public void SkipVisibility ()
  195. {
  196. DynamicMethod hello = new DynamicMethod ("Hello",
  197. typeof (string),
  198. new Type[] { typeof (string) },
  199. typeof (DynamicMethodTest).Module, true);
  200. ILGenerator helloIL = hello.GetILGenerator ();
  201. helloIL.Emit (OpCodes.Ldarg_0);
  202. helloIL.EmitCall (OpCodes.Call, typeof (DynamicMethodTest).GetMethod ("private_method", BindingFlags.Static|BindingFlags.NonPublic), null);
  203. helloIL.Emit (OpCodes.Ret);
  204. ReturnString del =
  205. (ReturnString) hello.CreateDelegate (typeof (ReturnString));
  206. Assert.AreEqual ("ABCD", del ("ABCD"));
  207. }
  208. [Test]
  209. public void ReturnType_Null ()
  210. {
  211. DynamicMethod hello = new DynamicMethod ("Hello",
  212. null,
  213. new Type[] { typeof (string) },
  214. typeof (DynamicMethodTest).Module, true);
  215. Assert.AreEqual (typeof (void), hello.ReturnType, "#1");
  216. ILGenerator helloIL = hello.GetILGenerator ();
  217. helloIL.Emit (OpCodes.Ret);
  218. DoNothing dn = (DoNothing) hello.CreateDelegate (typeof (DoNothing));
  219. dn ("whatever");
  220. object[] invokeArgs = { "Hello, World!" };
  221. object objRet = hello.Invoke (null, invokeArgs);
  222. Assert.IsNull (objRet, "#2");
  223. }
  224. [Test]
  225. public void Name_Empty ()
  226. {
  227. DynamicMethod hello = new DynamicMethod (string.Empty,
  228. typeof (int),
  229. new Type[] { typeof (string) },
  230. typeof (DynamicMethodTest).Module);
  231. Assert.AreEqual (string.Empty, hello.Name, "#1");
  232. DynamicMethod write = new DynamicMethod ("Write",
  233. typeof (int),
  234. new Type[] { typeof (string) },
  235. typeof (DynamicMethodTest));
  236. MethodInfo invokeWrite = write.GetBaseDefinition ();
  237. ILGenerator helloIL = hello.GetILGenerator ();
  238. helloIL.Emit (OpCodes.Ldarg_0);
  239. helloIL.EmitCall (OpCodes.Call, invokeWrite, null);
  240. helloIL.Emit (OpCodes.Ret);
  241. ILGenerator writeIL = write.GetILGenerator ();
  242. writeIL.Emit (OpCodes.Ldc_I4_2);
  243. writeIL.Emit (OpCodes.Ret);
  244. HelloInvoker hi =
  245. (HelloInvoker) hello.CreateDelegate (typeof (HelloInvoker));
  246. int ret = hi ("Hello, World!");
  247. Assert.AreEqual (2, ret, "#2");
  248. object[] invokeArgs = { "Hello, World!" };
  249. object objRet = hello.Invoke (null, invokeArgs);
  250. Assert.AreEqual (2, objRet, "#3");
  251. }
  252. [Test]
  253. public void Circular_Refs () {
  254. DynamicMethod m1 = new DynamicMethod("f1", typeof(int), new Type[] { typeof (int) },
  255. typeof(object));
  256. DynamicMethod m2 = new DynamicMethod("f2", typeof(int), new Type[] { typeof (int) },
  257. typeof(object));
  258. ILGenerator il1 = m1.GetILGenerator();
  259. ILGenerator il2 = m2.GetILGenerator();
  260. Label l = il1.DefineLabel ();
  261. //il1.EmitWriteLine ("f1");
  262. il1.Emit (OpCodes.Ldarg_0);
  263. il1.Emit (OpCodes.Ldc_I4_0);
  264. il1.Emit (OpCodes.Bne_Un, l);
  265. il1.Emit (OpCodes.Ldarg_0);
  266. il1.Emit (OpCodes.Ret);
  267. il1.MarkLabel (l);
  268. il1.Emit (OpCodes.Ldarg_0);
  269. il1.Emit (OpCodes.Ldc_I4_1);
  270. il1.Emit (OpCodes.Sub);
  271. il1.Emit (OpCodes.Call, m2);
  272. il1.Emit (OpCodes.Ret);
  273. //il2.EmitWriteLine("f2");
  274. il2.Emit(OpCodes.Ldarg_0);
  275. il2.Emit(OpCodes.Call, m1);
  276. il2.Emit(OpCodes.Ret);
  277. m1.Invoke(null, new object[] { 5 });
  278. }
  279. // Disabl known warning, the Field is never used directly from C#
  280. #pragma warning disable 414
  281. class Host {
  282. static string Field = "foo";
  283. }
  284. #pragma warning restore 414
  285. [Test]
  286. [Category ("NotDotNet")] // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=297416
  287. public void TestOwnerMemberAccess ()
  288. {
  289. DynamicMethod method = new DynamicMethod ("GetField",
  290. typeof (string), new Type [0], typeof (Host));
  291. ILGenerator il = method.GetILGenerator ();
  292. il.Emit (OpCodes.Ldsfld, typeof (Host).GetField (
  293. "Field", BindingFlags.Static | BindingFlags.NonPublic));
  294. il.Emit (OpCodes.Ret);
  295. string ret = (string) method.Invoke (null, new object [] {});
  296. Assert.AreEqual ("foo", ret, "#1");
  297. }
  298. [Test]
  299. public void AnonHosted ()
  300. {
  301. DynamicMethod hello = new DynamicMethod ("Hello",
  302. typeof (int),
  303. new Type[] { typeof (string) });
  304. ILGenerator helloIL = hello.GetILGenerator ();
  305. helloIL.Emit (OpCodes.Ldc_I4_2);
  306. helloIL.Emit (OpCodes.Ret);
  307. HelloInvoker hi =
  308. (HelloInvoker) hello.CreateDelegate (typeof (HelloInvoker));
  309. int ret = hi ("Hello, World!");
  310. Assert.AreEqual (2, ret);
  311. object[] invokeArgs = { "Hello, World!" };
  312. object objRet = hello.Invoke (null, invokeArgs);
  313. Assert.AreEqual (2, objRet);
  314. }
  315. public delegate int IntInvoker();
  316. public class Foo<T> {
  317. public virtual int Test () { return 99; }
  318. }
  319. [Test]
  320. public void ConstrainedPrexixDoesntCrash () //bug #529238
  321. {
  322. Type foo = typeof (Foo<int>);
  323. DynamicMethod dm = new DynamicMethod ("Hello", typeof (int), null);
  324. ILGenerator ilgen = dm.GetILGenerator ();
  325. ilgen.DeclareLocal (foo);
  326. ilgen.Emit (OpCodes.Newobj, foo.GetConstructor (new Type [0]));
  327. ilgen.Emit (OpCodes.Stloc_0);
  328. ilgen.Emit (OpCodes.Ldloca_S, 0);
  329. ilgen.Emit (OpCodes.Constrained, foo);
  330. ilgen.Emit (OpCodes.Callvirt, foo.GetMethod ("Test"));
  331. ilgen.Emit (OpCodes.Ret);
  332. IntInvoker hi = (IntInvoker) dm.CreateDelegate (typeof (IntInvoker));
  333. Assert.AreEqual (99, hi (), "#1");
  334. }
  335. // #575955
  336. [Test]
  337. public void Module_GetMethod () {
  338. AssemblyName assemblyName = new AssemblyName ();
  339. assemblyName.Name = "foo";
  340. AssemblyBuilder assembly =
  341. AppDomain.CurrentDomain.DefineDynamicAssembly (
  342. assemblyName, AssemblyBuilderAccess.RunAndSave);
  343. ModuleBuilder module = assembly.DefineDynamicModule ("foo.dll");
  344. var d = new DynamicMethod ("foo", typeof (int), new Type [] { typeof (int[,]) }, module);
  345. var ig = d.GetILGenerator ();
  346. ig.Emit (OpCodes.Ldarg_0);
  347. ig.Emit (OpCodes.Ldc_I4, 1);
  348. ig.Emit (OpCodes.Ldc_I4, 1);
  349. ig.Emit (OpCodes.Call, module.GetArrayMethod (typeof (int[,]), "Get", CallingConventions.Standard, typeof (int), new Type [] { typeof (int), typeof (int) }));
  350. ig.Emit (OpCodes.Ret);
  351. var del = (Func<int[,], int>)d.CreateDelegate (typeof (Func<int[,], int>));
  352. int[,] arr = new int [10, 10];
  353. arr [1, 1] = 5;
  354. Assert.AreEqual (5, del (arr));
  355. }
  356. [Test]
  357. [Category ("NotWorking")]
  358. public void InvalidUnicodeName ()
  359. {
  360. var name = new StringBuilder ().Append ('\udf45').Append ('\ud808');
  361. var method = new DynamicMethod (name.ToString (), typeof (bool), new Type [0]);
  362. var il = method.GetILGenerator ();
  363. il.Emit (OpCodes.Ldc_I4_1);
  364. il.Emit (OpCodes.Ret);
  365. var function = (Func<bool>) method.CreateDelegate (typeof (Func<bool>));
  366. Assert.IsTrue (function ());
  367. }
  368. [Test]
  369. [ExpectedException (typeof (InvalidOperationException))]
  370. public void GetMethodBody ()
  371. {
  372. var method = new DynamicMethod ("method", typeof (object), new Type [] { typeof (object) });
  373. var il = method.GetILGenerator ();
  374. il.Emit (OpCodes.Ldarg_0);
  375. il.Emit (OpCodes.Ret);
  376. var f = (Func<object, object>) method.CreateDelegate (typeof (Func<object, object>));
  377. f.Method.GetMethodBody ();
  378. }
  379. [Test]
  380. public void GetCustomAttributes ()
  381. {
  382. var method = new DynamicMethod ("method", typeof (void), new Type [] { });
  383. var methodImplAttrType = typeof (MethodImplAttribute);
  384. Assert.IsTrue (method.IsDefined (methodImplAttrType, true), "MethodImplAttribute is defined");
  385. // According to the spec, MethodImplAttribute is the
  386. // only custom attr that's present on a DynamicMethod.
  387. // And it's always a managed method with no inlining.
  388. var a1 = method.GetCustomAttributes (true);
  389. Assert.AreEqual (a1.Length, 1, "a1.Length == 1");
  390. Assert.AreEqual (a1[0].GetType (), methodImplAttrType, "a1[0] is a MethodImplAttribute");
  391. var options = (a1[0] as MethodImplAttribute).Value;
  392. Assert.IsTrue ((options & MethodImplOptions.NoInlining) != 0, "NoInlining is set");
  393. Assert.IsTrue ((options & MethodImplOptions.Unmanaged) == 0, "Unmanaged isn't set");
  394. // any other custom attribute type
  395. var extensionAttrType = typeof (ExtensionAttribute);
  396. Assert.IsFalse (method.IsDefined (extensionAttrType, true));
  397. Assert.AreEqual (Array.Empty<object>(), method.GetCustomAttributes (extensionAttrType, true));
  398. }
  399. public delegate object RetObj();
  400. [Test] //#640702
  401. public void GetCurrentMethodWorksWithDynamicMethods ()
  402. {
  403. DynamicMethod dm = new DynamicMethod("Foo", typeof(object), null);
  404. ILGenerator ilgen = dm.GetILGenerator();
  405. ilgen.Emit(OpCodes.Call, typeof(MethodBase).GetMethod("GetCurrentMethod"));
  406. ilgen.Emit(OpCodes.Ret);
  407. RetObj del = (RetObj)dm.CreateDelegate(typeof(RetObj));
  408. MethodInfo res = (MethodInfo)del();
  409. Assert.AreEqual (dm.Name, res.Name, "#1");
  410. }
  411. [StructLayout (LayoutKind.Explicit)]
  412. struct SizeOfTarget {
  413. [FieldOffset (0)] public int X;
  414. [FieldOffset (4)] public int Y;
  415. }
  416. [Test]
  417. public void SizeOf ()
  418. {
  419. var method = new DynamicMethod ("", typeof (int), Type.EmptyTypes);
  420. var il = method.GetILGenerator ();
  421. il.Emit (OpCodes.Sizeof, typeof (SizeOfTarget));
  422. il.Emit (OpCodes.Ret);
  423. var func = (Func<int>) method.CreateDelegate (typeof (Func<int>));
  424. var point_size = func ();
  425. Assert.AreEqual (8, point_size);
  426. }
  427. class TypedRefTarget {
  428. public string Name;
  429. }
  430. class ExceptionHandling_Test_Support
  431. {
  432. public static Exception Caught;
  433. public static string CaughtStackTrace;
  434. public static void ThrowMe ()
  435. {
  436. Caught = null;
  437. CaughtStackTrace = null;
  438. throw new Exception("test");
  439. }
  440. public static void Handler (Exception e)
  441. {
  442. Caught = e;
  443. CaughtStackTrace = e.StackTrace.ToString ();
  444. }
  445. }
  446. [Test]
  447. public void ExceptionHandling ()
  448. {
  449. var method = new DynamicMethod ("", typeof(void), new[] { typeof(int) }, typeof (DynamicMethodTest));
  450. var ig = method.GetILGenerator ();
  451. ig.BeginExceptionBlock();
  452. ig.Emit(OpCodes.Call, typeof(ExceptionHandling_Test_Support).GetMethod("ThrowMe"));
  453. ig.BeginCatchBlock(typeof(Exception));
  454. ig.Emit(OpCodes.Call, typeof(ExceptionHandling_Test_Support).GetMethod("Handler"));
  455. ig.EndExceptionBlock();
  456. ig.Emit(OpCodes.Ret);
  457. var invoke = (Action<int>) method.CreateDelegate (typeof(Action<int>));
  458. invoke (456324);
  459. Assert.IsNotNull (ExceptionHandling_Test_Support.Caught, "#1");
  460. var lines = ExceptionHandling_Test_Support.CaughtStackTrace.Split (new[] { Environment.NewLine }, StringSplitOptions.None);
  461. lines = lines.Where (l => !l.StartsWith ("[")).ToArray ();
  462. Assert.AreEqual (2, lines.Length, "#2");
  463. var st = new StackTrace (ExceptionHandling_Test_Support.Caught, 0, true);
  464. // Caught stack trace when dynamic method is gone
  465. Assert.AreEqual (ExceptionHandling_Test_Support.CaughtStackTrace, st.ToString (), "#3");
  466. // Catch handler stack trace inside dynamic method match
  467. Assert.AreEqual (ExceptionHandling_Test_Support.Caught.StackTrace, st.ToString (), "#4");
  468. }
  469. class ExceptionHandlingWithExceptionDispatchInfo_Test_Support
  470. {
  471. public static Exception Caught;
  472. public static string CaughtStackTrace;
  473. public static void ThrowMe ()
  474. {
  475. Caught = null;
  476. CaughtStackTrace = null;
  477. Exception e;
  478. try {
  479. throw new Exception("test");
  480. } catch (Exception e2) {
  481. e = e2;
  482. }
  483. var edi = ExceptionDispatchInfo.Capture(e);
  484. edi.Throw();
  485. }
  486. public static void Handler (Exception e)
  487. {
  488. var lines = e.StackTrace.Split (new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
  489. // Ignore Metadata
  490. lines = lines.Where (l => !l.StartsWith ("[")).ToArray ();
  491. Assert.AreEqual (4, lines.Length, "#1");
  492. Assert.IsTrue (lines [1].Contains ("---"), "#2");
  493. }
  494. }
  495. [Test]
  496. public void ExceptionHandlingWithExceptionDispatchInfo ()
  497. {
  498. var method = new DynamicMethod ("", typeof(void), new[] { typeof(int) }, typeof (DynamicMethodTest));
  499. var ig = method.GetILGenerator ();
  500. ig.BeginExceptionBlock();
  501. ig.Emit(OpCodes.Call, typeof(ExceptionHandlingWithExceptionDispatchInfo_Test_Support).GetMethod("ThrowMe"));
  502. ig.BeginCatchBlock(typeof(Exception));
  503. ig.Emit(OpCodes.Call, typeof(ExceptionHandlingWithExceptionDispatchInfo_Test_Support).GetMethod("Handler"));
  504. ig.EndExceptionBlock();
  505. ig.Emit(OpCodes.Ret);
  506. var invoke = (Action<int>) method.CreateDelegate (typeof(Action<int>));
  507. invoke (444);
  508. }
  509. static Func<int> EmitDelegate (DynamicMethod dm) {
  510. ILGenerator il = dm.GetILGenerator ();
  511. var ret_val = il.DeclareLocal (typeof (int));
  512. var leave_label = il.DefineLabel ();
  513. //ret = 1;
  514. il.Emit (OpCodes.Ldc_I4, 1);
  515. il.Emit (OpCodes.Stloc, ret_val);
  516. // try {
  517. il.BeginExceptionBlock ();
  518. // throw "hello";
  519. il.Emit (OpCodes.Ldstr, "hello");
  520. il.Emit (OpCodes.Throw, typeof (string));
  521. // ret = 2
  522. il.Emit (OpCodes.Ldc_I4, 2);
  523. il.Emit (OpCodes.Stloc, ret_val);
  524. // }
  525. il.Emit (OpCodes.Leave, leave_label);
  526. //catch (string)
  527. il.BeginCatchBlock (typeof (string));
  528. il.Emit (OpCodes.Pop);
  529. // ret = 3
  530. il.Emit (OpCodes.Ldc_I4, 3);
  531. il.Emit (OpCodes.Stloc, ret_val);
  532. //}
  533. il.Emit (OpCodes.Leave, leave_label);
  534. il.EndExceptionBlock ();
  535. il.MarkLabel (leave_label);
  536. //return ret;
  537. il.Emit (OpCodes.Ldloc, ret_val);
  538. il.Emit (OpCodes.Ret);
  539. var dele = (Func<int>)dm.CreateDelegate (typeof (Func<int>));
  540. return dele;
  541. }
  542. [Test] //see bxc #59334
  543. public void ExceptionWrapping ()
  544. {
  545. AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly (new AssemblyName ("ehatevfheiw"), AssemblyBuilderAccess.Run);
  546. AssemblyBuilder ab2 = AppDomain.CurrentDomain.DefineDynamicAssembly (new AssemblyName ("ddf4234"), AssemblyBuilderAccess.Run);
  547. CustomAttributeBuilder cab = new CustomAttributeBuilder (
  548. typeof (RuntimeCompatibilityAttribute).GetConstructor (new Type [0]),
  549. new object [0],
  550. new PropertyInfo[] { typeof (RuntimeCompatibilityAttribute).GetProperty ("WrapNonExceptionThrows") },
  551. new object[] { true });
  552. ab2.SetCustomAttribute (cab);
  553. AssemblyBuilder ab3 = AppDomain.CurrentDomain.DefineDynamicAssembly (new AssemblyName ("frfhfher"), AssemblyBuilderAccess.Run);
  554. //1 NamedArg. Property name: WrapNonExceptionThrows value: true (0x01)
  555. byte[] blob = new byte[] { 0x01, 0x00, 0x01, 0x00, 0x54, 0x02, 0x16, 0x57, 0x72, 0x61, 0x70, 0x4E, 0x6F, 0x6E, 0x45, 0x78,
  556. 0x63, 0x65, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x54, 0x68, 0x72, 0x6F, 0x77, 0x73, 0x01 };
  557. ab3.SetCustomAttribute (typeof (RuntimeCompatibilityAttribute).GetConstructor (new Type [0]), blob);
  558. DynamicMethod invoke_no_module = new DynamicMethod("throw_1", typeof (int), new Type [0]);
  559. DynamicMethod invoke_with_module = new DynamicMethod("throw_2", typeof (int), new Type [0], typeof (DynamicMethodTest).Module);
  560. DynamicMethod invoke_with_ab = new DynamicMethod("throw_3", typeof (int), new Type [0], ab.ManifestModule);
  561. DynamicMethod invoke_with_ab2 = new DynamicMethod("throw_4", typeof (int), new Type [0], ab2.ManifestModule);
  562. DynamicMethod invoke_with_ab3 = new DynamicMethod("throw_5", typeof (int), new Type [0], ab3.ManifestModule);
  563. int result = 0;
  564. try {
  565. int res = EmitDelegate (invoke_no_module)();
  566. Assert.AreEqual (3, res, "invoke_no_module bad return value");
  567. } catch (RuntimeWrappedException e) {
  568. Assert.Fail ("invoke_no_module threw RWE");
  569. }
  570. try {
  571. int res = EmitDelegate (invoke_with_module)();
  572. Assert.Fail ("invoke_with_module did not throw RWE");
  573. } catch (RuntimeWrappedException e) {
  574. }
  575. try {
  576. int res = EmitDelegate (invoke_with_ab)();
  577. Assert.AreEqual (3, res, "invoke_with_ab bad return value");
  578. } catch (RuntimeWrappedException e) {
  579. Assert.Fail ("invoke_with_ab threw RWE");
  580. }
  581. try {
  582. int res = EmitDelegate (invoke_with_ab2)();
  583. Assert.Fail ("invoke_with_ab2 did not throw RWE");
  584. } catch (RuntimeWrappedException e) {
  585. }
  586. try {
  587. int res = EmitDelegate (invoke_with_ab3)();
  588. Assert.Fail ("invoke_with_a3 did not throw RWE");
  589. } catch (RuntimeWrappedException e) {
  590. }
  591. }
  592. #if !MONODROID
  593. // RUNTIME: crash
  594. [Test]
  595. public void TypedRef ()
  596. {
  597. var method = new DynamicMethod ("", typeof (TypedRefTarget), new [] {typeof (TypedRefTarget)}, true);
  598. var il = method.GetILGenerator ();
  599. var tr = il.DeclareLocal (typeof (TypedReference));
  600. il.Emit (OpCodes.Ldarga, 0);
  601. il.Emit (OpCodes.Mkrefany, typeof (TypedRefTarget));
  602. il.Emit (OpCodes.Stloc, tr);
  603. il.Emit (OpCodes.Ldloc, tr);
  604. il.Emit (OpCodes.Call, GetType ().GetMethod ("AssertTypedRef", BindingFlags.NonPublic | BindingFlags.Static));
  605. il.Emit (OpCodes.Ldloc, tr);
  606. il.Emit (OpCodes.Refanyval, typeof (TypedRefTarget));
  607. il.Emit (OpCodes.Ldobj, typeof (TypedRefTarget));
  608. il.Emit (OpCodes.Ret);
  609. var f = (Func<TypedRefTarget, TypedRefTarget>) method.CreateDelegate (typeof (Func<TypedRefTarget, TypedRefTarget>));
  610. var target = new TypedRefTarget { Name = "Foo" };
  611. var rt = f (target);
  612. Assert.AreEqual (target, rt);
  613. }
  614. private static void AssertTypedRef (TypedReference tr)
  615. {
  616. Assert.AreEqual (typeof (TypedRefTarget), TypedReference.GetTargetType (tr));
  617. }
  618. #endif
  619. static Action GenerateProblematicMethod (bool add_extra, bool mismatch = false, bool use_vts = false)
  620. {
  621. Type this_type = typeof(object);
  622. Type bound_type = typeof(object);
  623. if (mismatch) {
  624. this_type = typeof (string);
  625. bound_type = typeof (DynamicMethodTest);
  626. } else if (use_vts) {
  627. this_type = typeof (int);
  628. bound_type = typeof (long);
  629. }
  630. Type[] args;
  631. if (add_extra)
  632. args = new[] { this_type };
  633. else
  634. args = new Type [0];
  635. var mb = new DynamicMethod("Peek", null, args, bound_type, true);
  636. var il = mb.GetILGenerator ();
  637. il.Emit(OpCodes.Ret);
  638. return (Action) mb.CreateDelegate(typeof(Action));
  639. }
  640. [Test]
  641. public void ExtraArgGetsIgnored ()
  642. {
  643. GenerateProblematicMethod (true) ();
  644. }
  645. [Test]
  646. public void ExactNumberOfArgsWork ()
  647. {
  648. GenerateProblematicMethod (false) ();
  649. }
  650. [Test]
  651. public void ExtraArgWithMismatchedTypes ()
  652. {
  653. GenerateProblematicMethod (true, mismatch: true) ();
  654. }
  655. [Test]
  656. [ExpectedException (typeof (ArgumentException))]
  657. public void ExtraArgWithValueType ()
  658. {
  659. GenerateProblematicMethod (true, use_vts: true) ();
  660. }
  661. }
  662. }