ExpressionTest_MakeBinary.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. // Permission is hereby granted, free of charge, to any person obtaining
  2. // a copy of this software and associated documentation files (the
  3. // "Software"), to deal in the Software without restriction, including
  4. // without limitation the rights to use, copy, modify, merge, publish,
  5. // distribute, sublicense, and/or sell copies of the Software, and to
  6. // permit persons to whom the Software is furnished to do so, subject to
  7. // the following conditions:
  8. //
  9. // The above copyright notice and this permission notice shall be
  10. // included in all copies or substantial portions of the Software.
  11. //
  12. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  13. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  14. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  15. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  16. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  17. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  18. //
  19. // Authors:
  20. // Miguel de Icaza <[email protected]>
  21. //
  22. using System;
  23. using System.Reflection;
  24. using System.Linq;
  25. using System.Linq.Expressions;
  26. using NUnit.Framework;
  27. namespace MonoTests.System.Linq.Expressions
  28. {
  29. [TestFixture]
  30. public class ExpressionTest_MakeBinary {
  31. public static int GoodMethod (string a, double d)
  32. {
  33. return 1;
  34. }
  35. public static int BadMethodSig_1 ()
  36. {
  37. return 1;
  38. }
  39. public static int BadMethodSig_2 (int a)
  40. {
  41. return 1;
  42. }
  43. public static int BadMethodSig_3 (int a, int b, int c)
  44. {
  45. return 1;
  46. }
  47. static MethodInfo GM (string n)
  48. {
  49. MethodInfo [] methods = typeof (ExpressionTest_MakeBinary).GetMethods (
  50. BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
  51. foreach (MethodInfo m in methods)
  52. if (m.Name == n)
  53. return m;
  54. throw new Exception (String.Format ("Method {0} not found", n));
  55. }
  56. [Test]
  57. public void MethodChecks ()
  58. {
  59. Expression left = Expression.Constant ("");
  60. Expression right = Expression.Constant (1.0);
  61. BinaryExpression r = Expression.Add (left, right, GM ("GoodMethod"));
  62. Assert.AreEqual (r.Type, typeof (int));
  63. }
  64. [Test]
  65. [ExpectedException(typeof (ArgumentException))]
  66. public void MethodCheck_BadArgs ()
  67. {
  68. Expression left = Expression.Constant ("");
  69. Expression right = Expression.Constant (1.0);
  70. Expression.Add (left, right, GM ("BadMethodSig_1"));
  71. }
  72. [Test]
  73. [ExpectedException(typeof (ArgumentException))]
  74. public void MethodCheck_BadArgs2 ()
  75. {
  76. Expression left = Expression.Constant ("");
  77. Expression right = Expression.Constant (1.0);
  78. Expression.Add (left, right, GM ("BadMethodSig_2"));
  79. }
  80. [Test]
  81. [ExpectedException(typeof (ArgumentException))]
  82. public void MethodCheck_BadArgs3 ()
  83. {
  84. Expression left = Expression.Constant ("");
  85. Expression right = Expression.Constant (1.0);
  86. Expression.Add (left, right, GM ("BadMethodSig_3"));
  87. }
  88. static void PassInt (ExpressionType nt)
  89. {
  90. Expression left = Expression.Constant (1);
  91. Expression right = Expression.Constant (1);
  92. Expression.MakeBinary (nt, left, right);
  93. }
  94. #if false
  95. static void FailInt (ExpressionType nt)
  96. {
  97. Expression left = Expression.Constant (1);
  98. Expression right = Expression.Constant (1);
  99. try {
  100. Expression.MakeBinary (nt, left, right);
  101. } catch (ArgumentException){
  102. return;
  103. }
  104. // If we get here, there was an error
  105. Assert.Fail ("FailInt failed while creating an {0}", nt);
  106. }
  107. #endif
  108. //
  109. // Checks that we complain on the proper ExpressionTypes
  110. //
  111. [Test]
  112. public void TestBinaryCtor ()
  113. {
  114. PassInt (ExpressionType.Add);
  115. PassInt (ExpressionType.AddChecked);
  116. PassInt (ExpressionType.And);
  117. PassInt (ExpressionType.Divide);
  118. PassInt (ExpressionType.Equal);
  119. PassInt (ExpressionType.ExclusiveOr);
  120. PassInt (ExpressionType.GreaterThan);
  121. PassInt (ExpressionType.GreaterThanOrEqual);
  122. PassInt (ExpressionType.LeftShift);
  123. PassInt (ExpressionType.LessThan);
  124. PassInt (ExpressionType.LessThanOrEqual);
  125. PassInt (ExpressionType.Multiply);
  126. PassInt (ExpressionType.MultiplyChecked);
  127. PassInt (ExpressionType.NotEqual);
  128. PassInt (ExpressionType.Or);
  129. PassInt (ExpressionType.Modulo);
  130. PassInt (ExpressionType.RightShift);
  131. PassInt (ExpressionType.Subtract);
  132. PassInt (ExpressionType.SubtractChecked);
  133. // Remove comment when the code is implemented:
  134. //FailInt (ExpressionType.AndAlso);
  135. //FailInt (ExpressionType.OrElse);
  136. //This should test for types, not operation: FailInt (ExpressionType.Power);
  137. #if false
  138. // These currently fail, because it now goes directly to the nodes, instead of doing
  139. // a first-pass check; REmove when its all done.
  140. FailInt (ExpressionType.ArrayLength);
  141. FailInt (ExpressionType.ArrayIndex);
  142. FailInt (ExpressionType.Call);
  143. FailInt (ExpressionType.Coalesce);
  144. FailInt (ExpressionType.Conditional);
  145. FailInt (ExpressionType.Constant);
  146. FailInt (ExpressionType.Convert);
  147. FailInt (ExpressionType.ConvertChecked);
  148. FailInt (ExpressionType.Invoke);
  149. FailInt (ExpressionType.Lambda);
  150. FailInt (ExpressionType.ListInit);
  151. FailInt (ExpressionType.MemberAccess);
  152. FailInt (ExpressionType.MemberInit);
  153. FailInt (ExpressionType.Negate);
  154. FailInt (ExpressionType.UnaryPlus);
  155. FailInt (ExpressionType.NegateChecked);
  156. FailInt (ExpressionType.New);
  157. FailInt (ExpressionType.NewArrayInit);
  158. FailInt (ExpressionType.NewArrayBounds);
  159. FailInt (ExpressionType.Not);
  160. FailInt (ExpressionType.Parameter);
  161. FailInt (ExpressionType.Quote);
  162. FailInt (ExpressionType.TypeAs);
  163. FailInt (ExpressionType.TypeIs);
  164. #endif
  165. }
  166. public delegate Expression BinaryExpr (Expression a, Expression b);
  167. public T CodeGen<T> (BinaryExpr bin, T v1, T v2)
  168. {
  169. Expression<Func<T>> l = Expression.Lambda<Func<T>> (
  170. bin (Expression.Constant(v1), Expression.Constant(v2)),
  171. new ParameterExpression [0]);
  172. Func<T> fi = l.Compile ();
  173. return fi ();
  174. }
  175. [Test]
  176. public void TestOperations ()
  177. {
  178. Assert.AreEqual (30, CodeGen<int> ((a, b) => Expression.Add (a, b), 10, 20));
  179. Assert.AreEqual (-12, CodeGen<int> ((a, b) => Expression.Subtract (a, b), 11, 23));
  180. Assert.AreEqual (253, CodeGen<int> ((a, b) => Expression.Multiply (a, b), 11, 23));
  181. Assert.AreEqual (33, CodeGen<int> ((a, b) => Expression.Divide (a, b), 100, 3));
  182. Assert.AreEqual (100.0/3, CodeGen<double> ((a, b) => Expression.Divide (a, b), 100, 3));
  183. }
  184. void CTest<T> (ExpressionType node, bool r, T a, T b)
  185. {
  186. ParameterExpression pa = Expression.Parameter(typeof(T), "a");
  187. ParameterExpression pb = Expression.Parameter(typeof(T), "b");
  188. BinaryExpression p = Expression.MakeBinary (node, Expression.Constant (a), Expression.Constant(b));
  189. Expression<Func<T,T,bool>> pexpr = Expression.Lambda<Func<T,T,bool>> (
  190. p, new ParameterExpression [] { pa, pb });
  191. Func<T,T,bool> compiled = pexpr.Compile ();
  192. Assert.AreEqual (r, compiled (a, b), String.Format ("{0} ({1},{2}) == {3}", node, a, b, r));
  193. }
  194. [Test]
  195. public void ComparisonTests ()
  196. {
  197. ExpressionType t = ExpressionType.Equal;
  198. CTest<byte> (t, true, 10, 10);
  199. CTest<sbyte> (t, false, 1, 5);
  200. CTest<sbyte> (t, true, 1, 1);
  201. CTest<int> (t, true, 1, 1);
  202. CTest<double> (t, true, 1.0, 1.0);
  203. CTest<string> (t, true, "", "");
  204. CTest<string> (t, true, "Hey", "Hey");
  205. CTest<string> (t, false, "Hey", "There");
  206. t = ExpressionType.NotEqual;
  207. CTest<byte> (t, false, 10, 10);
  208. CTest<sbyte> (t, true, 1, 5);
  209. CTest<sbyte> (t, false, 1, 1);
  210. CTest<int> (t, false, 1, 1);
  211. CTest<double> (t, false, 1.0, 1.0);
  212. CTest<double> (t, false, 1.0, 1.0);
  213. CTest<string> (t, false, "", "");
  214. CTest<string> (t, false, "Hey", "Hey");
  215. CTest<string> (t, true, "Hey", "There");
  216. t = ExpressionType.GreaterThan;
  217. CTest<byte> (t, true, 5, 1);
  218. CTest<byte> (t, false, 10, 10);
  219. CTest<sbyte> (t, false, 1, 5);
  220. CTest<sbyte> (t, false, 1, 1);
  221. CTest<int> (t, false, 1, 1);
  222. CTest<uint> (t, true, 1, 0);
  223. CTest<ulong> (t, true, Int64.MaxValue, 0);
  224. CTest<double> (t, false, 1.0, 1.0);
  225. CTest<double> (t, false, 1.0, 1.0);
  226. t = ExpressionType.LessThan;
  227. CTest<byte> (t, false, 5, 1);
  228. CTest<byte> (t, false, 10, 10);
  229. CTest<sbyte> (t, true, 1, 5);
  230. CTest<sbyte> (t, false, 1, 1);
  231. CTest<int> (t, false, 1, 1);
  232. CTest<uint> (t, false, 1, 0);
  233. CTest<ulong> (t, false, Int64.MaxValue, 0);
  234. CTest<double> (t, false, 1.0, 1.0);
  235. CTest<double> (t, false, 1.0, 1.0);
  236. t = ExpressionType.GreaterThanOrEqual;
  237. CTest<byte> (t, true, 5, 1);
  238. CTest<byte> (t, true, 10, 10);
  239. CTest<sbyte> (t, false, 1, 5);
  240. CTest<sbyte> (t, true, 1, 1);
  241. CTest<int> (t, true, 1, 1);
  242. CTest<uint> (t, true, 1, 0);
  243. CTest<ulong> (t, true, Int64.MaxValue, 0);
  244. CTest<double> (t, true, 1.0, 1.0);
  245. CTest<double> (t, true, 1.0, 1.0);
  246. t = ExpressionType.LessThanOrEqual;
  247. CTest<byte> (t, false, 5, 1);
  248. CTest<byte> (t, true, 10, 10);
  249. CTest<sbyte> (t, true, 1, 5);
  250. CTest<sbyte> (t, true, 1, 1);
  251. CTest<int> (t, true, 1, 1);
  252. CTest<uint> (t, false, 1, 0);
  253. CTest<ulong> (t, false, Int64.MaxValue, 0);
  254. CTest<double> (t, true, 1.0, 1.0);
  255. CTest<double> (t, true, 1.0, 1.0);
  256. }
  257. }
  258. }