DynamicMethodTest.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  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. #if NET_2_0
  9. using System;
  10. using System.Reflection;
  11. using System.Reflection.Emit;
  12. using System.Runtime.InteropServices;
  13. using System.Text;
  14. using NUnit.Framework;
  15. namespace MonoTests.System.Reflection.Emit
  16. {
  17. [TestFixture]
  18. public class DynamicMethodTest
  19. {
  20. private delegate int HelloInvoker (string msg);
  21. [Test]
  22. public void Constructor1_Name_Null ()
  23. {
  24. try {
  25. new DynamicMethod (null,
  26. typeof (void),
  27. new Type[] { typeof (string) },
  28. typeof (DynamicMethodTest).Module);
  29. Assert.Fail ("#1");
  30. } catch (ArgumentNullException ex) {
  31. Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
  32. Assert.AreEqual ("name", ex.ParamName, "#3");
  33. Assert.IsNull (ex.InnerException, "#4");
  34. }
  35. }
  36. [Test]
  37. public void Constructor2_Name_Null ()
  38. {
  39. try {
  40. new DynamicMethod (null,
  41. typeof (void),
  42. new Type[] { typeof (string) },
  43. typeof (DynamicMethodTest));
  44. Assert.Fail ("#1");
  45. } catch (ArgumentNullException ex) {
  46. Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
  47. Assert.AreEqual ("name", ex.ParamName, "#3");
  48. Assert.IsNull (ex.InnerException, "#4");
  49. }
  50. }
  51. [Test]
  52. public void Constructor3_Name_Null ()
  53. {
  54. try {
  55. new DynamicMethod (null,
  56. typeof (void),
  57. new Type[] { typeof (string) },
  58. typeof (DynamicMethodTest).Module, true);
  59. Assert.Fail ("#1");
  60. } catch (ArgumentNullException ex) {
  61. Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
  62. Assert.AreEqual ("name", ex.ParamName, "#3");
  63. Assert.IsNull (ex.InnerException, "#4");
  64. }
  65. }
  66. [Test]
  67. public void Constructor4_Name_Null ()
  68. {
  69. try {
  70. new DynamicMethod (null,
  71. typeof (void),
  72. new Type[] { typeof (string) },
  73. typeof (DynamicMethodTest), true);
  74. Assert.Fail ("#1");
  75. } catch (ArgumentNullException ex) {
  76. Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
  77. Assert.AreEqual ("name", ex.ParamName, "#3");
  78. Assert.IsNull (ex.InnerException, "#4");
  79. }
  80. }
  81. [Test]
  82. public void Constructor5_Name_Null ()
  83. {
  84. try {
  85. new DynamicMethod (null,
  86. MethodAttributes.Public | MethodAttributes.Static,
  87. CallingConventions.Standard,
  88. typeof (void),
  89. new Type[] { typeof (string) },
  90. typeof (DynamicMethodTest).Module, true);
  91. Assert.Fail ("#1");
  92. } catch (ArgumentNullException ex) {
  93. Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
  94. Assert.AreEqual ("name", ex.ParamName, "#3");
  95. Assert.IsNull (ex.InnerException, "#4");
  96. }
  97. }
  98. [Test]
  99. public void Constructor6_Name_Null ()
  100. {
  101. try {
  102. new DynamicMethod (null,
  103. MethodAttributes.Public | MethodAttributes.Static,
  104. CallingConventions.Standard,
  105. typeof (void),
  106. new Type[] { typeof (string) },
  107. typeof (DynamicMethodTest), true);
  108. Assert.Fail ("#1");
  109. } catch (ArgumentNullException ex) {
  110. Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
  111. Assert.AreEqual ("name", ex.ParamName, "#3");
  112. Assert.IsNull (ex.InnerException, "#4");
  113. }
  114. }
  115. [Test]
  116. public void OwnerCantBeArray ()
  117. {
  118. TestOwner (typeof (int[]));
  119. }
  120. [Test]
  121. public void OwnerCantBeInterface ()
  122. {
  123. TestOwner (typeof (global::System.Collections.IEnumerable));
  124. }
  125. private void TestOwner (Type owner)
  126. {
  127. try {
  128. new DynamicMethod ("Name", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard,
  129. typeof(void), new Type[] { }, owner, true);
  130. Assert.Fail (string.Format ("Created dynamic method with owner being {0}.", owner));
  131. } catch (ArgumentException) {
  132. }
  133. }
  134. [Test] // bug #78253
  135. public void DynamicMethodReference ()
  136. {
  137. DynamicMethod hello = new DynamicMethod ("Hello",
  138. typeof (int),
  139. new Type[] { typeof (string) },
  140. typeof (DynamicMethodTest).Module);
  141. Assert.IsNull (hello.DeclaringType, "#1");
  142. DynamicMethod write = new DynamicMethod ("Write",
  143. typeof (int),
  144. new Type[] { typeof (string) },
  145. typeof (DynamicMethodTest));
  146. Assert.IsNull (hello.DeclaringType, "#2");
  147. MethodInfo invokeWrite = write.GetBaseDefinition ();
  148. ILGenerator helloIL = hello.GetILGenerator ();
  149. helloIL.Emit (OpCodes.Ldarg_0);
  150. helloIL.EmitCall (OpCodes.Call, invokeWrite, null);
  151. helloIL.Emit (OpCodes.Ret);
  152. ILGenerator writeIL = write.GetILGenerator ();
  153. writeIL.Emit (OpCodes.Ldc_I4_2);
  154. writeIL.Emit (OpCodes.Ret);
  155. HelloInvoker hi =
  156. (HelloInvoker) hello.CreateDelegate (typeof (HelloInvoker));
  157. int ret = hi ("Hello, World!");
  158. Assert.AreEqual (2, ret, "#3");
  159. object[] invokeArgs = { "Hello, World!" };
  160. object objRet = hello.Invoke (null, invokeArgs);
  161. Assert.AreEqual (2, objRet, "#4");
  162. }
  163. [Test]
  164. public void EmptyMethodBody ()
  165. {
  166. DynamicMethod hello = new DynamicMethod ("Hello",
  167. typeof (int),
  168. new Type[] { typeof (string) },
  169. typeof (DynamicMethodTest).Module);
  170. object[] invokeArgs = { "Hello, World!" };
  171. // no IL generator
  172. try {
  173. hello.Invoke (null, invokeArgs);
  174. Assert.Fail ("#1");
  175. } catch (InvalidOperationException) {
  176. }
  177. // empty method body
  178. hello.GetILGenerator ();
  179. try {
  180. hello.Invoke (null, invokeArgs);
  181. Assert.Fail ("#2");
  182. } catch (InvalidOperationException) {
  183. }
  184. }
  185. private delegate string ReturnString (string msg);
  186. private delegate void DoNothing (string msg);
  187. private static string private_method (string s) {
  188. return s;
  189. }
  190. [Test]
  191. public void SkipVisibility ()
  192. {
  193. DynamicMethod hello = new DynamicMethod ("Hello",
  194. typeof (string),
  195. new Type[] { typeof (string) },
  196. typeof (DynamicMethodTest).Module, true);
  197. ILGenerator helloIL = hello.GetILGenerator ();
  198. helloIL.Emit (OpCodes.Ldarg_0);
  199. helloIL.EmitCall (OpCodes.Call, typeof (DynamicMethodTest).GetMethod ("private_method", BindingFlags.Static|BindingFlags.NonPublic), null);
  200. helloIL.Emit (OpCodes.Ret);
  201. ReturnString del =
  202. (ReturnString) hello.CreateDelegate (typeof (ReturnString));
  203. Assert.AreEqual ("ABCD", del ("ABCD"));
  204. }
  205. [Test]
  206. public void ReturnType_Null ()
  207. {
  208. DynamicMethod hello = new DynamicMethod ("Hello",
  209. null,
  210. new Type[] { typeof (string) },
  211. typeof (DynamicMethodTest).Module, true);
  212. Assert.AreEqual (typeof (void), hello.ReturnType, "#1");
  213. ILGenerator helloIL = hello.GetILGenerator ();
  214. helloIL.Emit (OpCodes.Ret);
  215. DoNothing dn = (DoNothing) hello.CreateDelegate (typeof (DoNothing));
  216. dn ("whatever");
  217. object[] invokeArgs = { "Hello, World!" };
  218. object objRet = hello.Invoke (null, invokeArgs);
  219. Assert.IsNull (objRet, "#2");
  220. }
  221. [Test]
  222. public void Name_Empty ()
  223. {
  224. DynamicMethod hello = new DynamicMethod (string.Empty,
  225. typeof (int),
  226. new Type[] { typeof (string) },
  227. typeof (DynamicMethodTest).Module);
  228. Assert.AreEqual (string.Empty, hello.Name, "#1");
  229. DynamicMethod write = new DynamicMethod ("Write",
  230. typeof (int),
  231. new Type[] { typeof (string) },
  232. typeof (DynamicMethodTest));
  233. MethodInfo invokeWrite = write.GetBaseDefinition ();
  234. ILGenerator helloIL = hello.GetILGenerator ();
  235. helloIL.Emit (OpCodes.Ldarg_0);
  236. helloIL.EmitCall (OpCodes.Call, invokeWrite, null);
  237. helloIL.Emit (OpCodes.Ret);
  238. ILGenerator writeIL = write.GetILGenerator ();
  239. writeIL.Emit (OpCodes.Ldc_I4_2);
  240. writeIL.Emit (OpCodes.Ret);
  241. HelloInvoker hi =
  242. (HelloInvoker) hello.CreateDelegate (typeof (HelloInvoker));
  243. int ret = hi ("Hello, World!");
  244. Assert.AreEqual (2, ret, "#2");
  245. object[] invokeArgs = { "Hello, World!" };
  246. object objRet = hello.Invoke (null, invokeArgs);
  247. Assert.AreEqual (2, objRet, "#3");
  248. }
  249. [Test]
  250. public void Circular_Refs () {
  251. DynamicMethod m1 = new DynamicMethod("f1", typeof(int), new Type[] { typeof (int) },
  252. typeof(object));
  253. DynamicMethod m2 = new DynamicMethod("f2", typeof(int), new Type[] { typeof (int) },
  254. typeof(object));
  255. ILGenerator il1 = m1.GetILGenerator();
  256. ILGenerator il2 = m2.GetILGenerator();
  257. Label l = il1.DefineLabel ();
  258. //il1.EmitWriteLine ("f1");
  259. il1.Emit (OpCodes.Ldarg_0);
  260. il1.Emit (OpCodes.Ldc_I4_0);
  261. il1.Emit (OpCodes.Bne_Un, l);
  262. il1.Emit (OpCodes.Ldarg_0);
  263. il1.Emit (OpCodes.Ret);
  264. il1.MarkLabel (l);
  265. il1.Emit (OpCodes.Ldarg_0);
  266. il1.Emit (OpCodes.Ldc_I4_1);
  267. il1.Emit (OpCodes.Sub);
  268. il1.Emit (OpCodes.Call, m2);
  269. il1.Emit (OpCodes.Ret);
  270. //il2.EmitWriteLine("f2");
  271. il2.Emit(OpCodes.Ldarg_0);
  272. il2.Emit(OpCodes.Call, m1);
  273. il2.Emit(OpCodes.Ret);
  274. m1.Invoke(null, new object[] { 5 });
  275. }
  276. // Disabl known warning, the Field is never used directly from C#
  277. #pragma warning disable 414
  278. class Host {
  279. static string Field = "foo";
  280. }
  281. #pragma warning restore 414
  282. [Test]
  283. [Category ("NotDotNet")] // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=297416
  284. public void TestOwnerMemberAccess ()
  285. {
  286. DynamicMethod method = new DynamicMethod ("GetField",
  287. typeof (string), new Type [0], typeof (Host));
  288. ILGenerator il = method.GetILGenerator ();
  289. il.Emit (OpCodes.Ldsfld, typeof (Host).GetField (
  290. "Field", BindingFlags.Static | BindingFlags.NonPublic));
  291. il.Emit (OpCodes.Ret);
  292. string ret = (string) method.Invoke (null, new object [] {});
  293. Assert.AreEqual ("foo", ret, "#1");
  294. }
  295. [Test]
  296. public void AnonHosted ()
  297. {
  298. DynamicMethod hello = new DynamicMethod ("Hello",
  299. typeof (int),
  300. new Type[] { typeof (string) });
  301. ILGenerator helloIL = hello.GetILGenerator ();
  302. helloIL.Emit (OpCodes.Ldc_I4_2);
  303. helloIL.Emit (OpCodes.Ret);
  304. HelloInvoker hi =
  305. (HelloInvoker) hello.CreateDelegate (typeof (HelloInvoker));
  306. int ret = hi ("Hello, World!");
  307. Assert.AreEqual (2, ret);
  308. object[] invokeArgs = { "Hello, World!" };
  309. object objRet = hello.Invoke (null, invokeArgs);
  310. Assert.AreEqual (2, objRet);
  311. }
  312. public delegate int IntInvoker();
  313. public class Foo<T> {
  314. public virtual int Test () { return 99; }
  315. }
  316. [Test]
  317. public void ConstrainedPrexixDoesntCrash () //bug #529238
  318. {
  319. Type foo = typeof (Foo<int>);
  320. DynamicMethod dm = new DynamicMethod ("Hello", typeof (int), null);
  321. ILGenerator ilgen = dm.GetILGenerator ();
  322. ilgen.DeclareLocal (foo);
  323. ilgen.Emit (OpCodes.Newobj, foo.GetConstructor (new Type [0]));
  324. ilgen.Emit (OpCodes.Stloc_0);
  325. ilgen.Emit (OpCodes.Ldloca_S, 0);
  326. ilgen.Emit (OpCodes.Constrained, foo);
  327. ilgen.Emit (OpCodes.Callvirt, foo.GetMethod ("Test"));
  328. ilgen.Emit (OpCodes.Ret);
  329. IntInvoker hi = (IntInvoker) dm.CreateDelegate (typeof (IntInvoker));
  330. Assert.AreEqual (99, hi (), "#1");
  331. }
  332. // #575955
  333. [Test]
  334. public void Module_GetMethod () {
  335. AssemblyName assemblyName = new AssemblyName ();
  336. assemblyName.Name = "foo";
  337. AssemblyBuilder assembly =
  338. AppDomain.CurrentDomain.DefineDynamicAssembly (
  339. assemblyName, AssemblyBuilderAccess.RunAndSave);
  340. ModuleBuilder module = assembly.DefineDynamicModule ("foo.dll");
  341. var d = new DynamicMethod ("foo", typeof (int), new Type [] { typeof (int[,]) }, module);
  342. var ig = d.GetILGenerator ();
  343. ig.Emit (OpCodes.Ldarg_0);
  344. ig.Emit (OpCodes.Ldc_I4, 1);
  345. ig.Emit (OpCodes.Ldc_I4, 1);
  346. ig.Emit (OpCodes.Call, module.GetArrayMethod (typeof (int[,]), "Get", CallingConventions.Standard, typeof (int), new Type [] { typeof (int), typeof (int) }));
  347. ig.Emit (OpCodes.Ret);
  348. var del = (Func<int[,], int>)d.CreateDelegate (typeof (Func<int[,], int>));
  349. int[,] arr = new int [10, 10];
  350. arr [1, 1] = 5;
  351. Assert.AreEqual (5, del (arr));
  352. }
  353. [Test]
  354. [Category ("NotWorking")]
  355. public void InvalidUnicodeName ()
  356. {
  357. var name = new StringBuilder ().Append ('\udf45').Append ('\ud808');
  358. var method = new DynamicMethod (name.ToString (), typeof (bool), new Type [0]);
  359. var il = method.GetILGenerator ();
  360. il.Emit (OpCodes.Ldc_I4_1);
  361. il.Emit (OpCodes.Ret);
  362. var function = (Func<bool>) method.CreateDelegate (typeof (Func<bool>));
  363. Assert.IsTrue (function ());
  364. }
  365. [Test]
  366. [ExpectedException (typeof (InvalidOperationException))]
  367. public void GetMethodBody ()
  368. {
  369. var method = new DynamicMethod ("method", typeof (object), new Type [] { typeof (object) });
  370. var il = method.GetILGenerator ();
  371. il.Emit (OpCodes.Ldarg_0);
  372. il.Emit (OpCodes.Ret);
  373. var f = (Func<object, object>) method.CreateDelegate (typeof (Func<object, object>));
  374. f.Method.GetMethodBody ();
  375. }
  376. public delegate object RetObj();
  377. [Test] //#640702
  378. public void GetCurrentMethodWorksWithDynamicMethods ()
  379. {
  380. DynamicMethod dm = new DynamicMethod("Foo", typeof(object), null);
  381. ILGenerator ilgen = dm.GetILGenerator();
  382. ilgen.Emit(OpCodes.Call, typeof(MethodBase).GetMethod("GetCurrentMethod"));
  383. ilgen.Emit(OpCodes.Ret);
  384. RetObj del = (RetObj)dm.CreateDelegate(typeof(RetObj));
  385. MethodInfo res = (MethodInfo)del();
  386. Assert.AreEqual (dm.Name, res.Name, "#1");
  387. }
  388. [StructLayout (LayoutKind.Explicit)]
  389. struct SizeOfTarget {
  390. [FieldOffset (0)] public int X;
  391. [FieldOffset (4)] public int Y;
  392. }
  393. [Test]
  394. public void SizeOf ()
  395. {
  396. var method = new DynamicMethod ("", typeof (int), Type.EmptyTypes);
  397. var il = method.GetILGenerator ();
  398. il.Emit (OpCodes.Sizeof, typeof (SizeOfTarget));
  399. il.Emit (OpCodes.Ret);
  400. var func = (Func<int>) method.CreateDelegate (typeof (Func<int>));
  401. var point_size = func ();
  402. Assert.AreEqual (8, point_size);
  403. }
  404. class TypedRefTarget {
  405. public string Name;
  406. }
  407. [Test]
  408. public void TypedRef ()
  409. {
  410. var method = new DynamicMethod ("", typeof (TypedRefTarget), new [] {typeof (TypedRefTarget)}, true);
  411. var il = method.GetILGenerator ();
  412. var tr = il.DeclareLocal (typeof (TypedReference));
  413. il.Emit (OpCodes.Ldarga, 0);
  414. il.Emit (OpCodes.Mkrefany, typeof (TypedRefTarget));
  415. il.Emit (OpCodes.Stloc, tr);
  416. il.Emit (OpCodes.Ldloc, tr);
  417. il.Emit (OpCodes.Call, GetType ().GetMethod ("AssertTypedRef", BindingFlags.NonPublic | BindingFlags.Static));
  418. il.Emit (OpCodes.Ldloc, tr);
  419. il.Emit (OpCodes.Refanyval, typeof (TypedRefTarget));
  420. il.Emit (OpCodes.Ldobj, typeof (TypedRefTarget));
  421. il.Emit (OpCodes.Ret);
  422. var f = (Func<TypedRefTarget, TypedRefTarget>) method.CreateDelegate (typeof (Func<TypedRefTarget, TypedRefTarget>));
  423. var target = new TypedRefTarget { Name = "Foo" };
  424. var rt = f (target);
  425. Assert.AreEqual (target, rt);
  426. }
  427. private static void AssertTypedRef (TypedReference tr)
  428. {
  429. Assert.AreEqual (typeof (TypedRefTarget), TypedReference.GetTargetType (tr));
  430. }
  431. }
  432. }
  433. #endif