ExpressionTest_MakeBinary.cs 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  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. static void FailInt (ExpressionType nt)
  95. {
  96. Expression left = Expression.Constant (1);
  97. Expression right = Expression.Constant (1);
  98. try {
  99. Expression.MakeBinary (nt, left, right);
  100. } catch (ArgumentException) {
  101. return;
  102. } catch (InvalidOperationException) {
  103. return;
  104. }
  105. // If we get here, there was an error
  106. Assert.Fail ("FailInt failed while creating an {0}", nt);
  107. }
  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. FailInt (ExpressionType.AndAlso);
  134. FailInt (ExpressionType.OrElse);
  135. FailInt (ExpressionType.Power);
  136. FailInt (ExpressionType.ArrayLength);
  137. FailInt (ExpressionType.ArrayIndex);
  138. FailInt (ExpressionType.Call);
  139. FailInt (ExpressionType.Coalesce);
  140. FailInt (ExpressionType.Conditional);
  141. FailInt (ExpressionType.Constant);
  142. FailInt (ExpressionType.Convert);
  143. FailInt (ExpressionType.ConvertChecked);
  144. FailInt (ExpressionType.Invoke);
  145. FailInt (ExpressionType.Lambda);
  146. FailInt (ExpressionType.ListInit);
  147. FailInt (ExpressionType.MemberAccess);
  148. FailInt (ExpressionType.MemberInit);
  149. FailInt (ExpressionType.Negate);
  150. FailInt (ExpressionType.UnaryPlus);
  151. FailInt (ExpressionType.NegateChecked);
  152. FailInt (ExpressionType.New);
  153. FailInt (ExpressionType.NewArrayInit);
  154. FailInt (ExpressionType.NewArrayBounds);
  155. FailInt (ExpressionType.Not);
  156. FailInt (ExpressionType.Parameter);
  157. FailInt (ExpressionType.Quote);
  158. FailInt (ExpressionType.TypeAs);
  159. FailInt (ExpressionType.TypeIs);
  160. }
  161. public T CodeGen<T> (Func<Expression, Expression, Expression> bin, T v1, T v2)
  162. {
  163. var lambda = Expression.Lambda<Func<T>> (bin (v1.ToConstant (), v2.ToConstant ())).Compile ();
  164. return lambda ();
  165. }
  166. [Test]
  167. public void TestOperations ()
  168. {
  169. Assert.AreEqual (30, CodeGen<int> ((a, b) => Expression.Add (a, b), 10, 20));
  170. Assert.AreEqual (-12, CodeGen<int> ((a, b) => Expression.Subtract (a, b), 11, 23));
  171. Assert.AreEqual (253, CodeGen<int> ((a, b) => Expression.Multiply (a, b), 11, 23));
  172. Assert.AreEqual (33, CodeGen<int> ((a, b) => Expression.Divide (a, b), 100, 3));
  173. Assert.AreEqual (100.0/3, CodeGen<double> ((a, b) => Expression.Divide (a, b), 100, 3));
  174. }
  175. void CTest<T> (ExpressionType node, bool r, T a, T b)
  176. {
  177. ParameterExpression pa = Expression.Parameter(typeof(T), "a");
  178. ParameterExpression pb = Expression.Parameter(typeof(T), "b");
  179. BinaryExpression p = Expression.MakeBinary (node, Expression.Constant (a), Expression.Constant(b));
  180. Expression<Func<T,T,bool>> pexpr = Expression.Lambda<Func<T,T,bool>> (
  181. p, new ParameterExpression [] { pa, pb });
  182. Func<T,T,bool> compiled = pexpr.Compile ();
  183. Assert.AreEqual (r, compiled (a, b), String.Format ("{0} ({1},{2}) == {3}", node, a, b, r));
  184. }
  185. [Test]
  186. public void ComparisonTests ()
  187. {
  188. ExpressionType t = ExpressionType.Equal;
  189. CTest<byte> (t, true, 10, 10);
  190. CTest<sbyte> (t, false, 1, 5);
  191. CTest<sbyte> (t, true, 1, 1);
  192. CTest<int> (t, true, 1, 1);
  193. CTest<double> (t, true, 1.0, 1.0);
  194. CTest<string> (t, true, "", "");
  195. CTest<string> (t, true, "Hey", "Hey");
  196. CTest<string> (t, false, "Hey", "There");
  197. t = ExpressionType.NotEqual;
  198. CTest<byte> (t, false, 10, 10);
  199. CTest<sbyte> (t, true, 1, 5);
  200. CTest<sbyte> (t, false, 1, 1);
  201. CTest<int> (t, false, 1, 1);
  202. CTest<double> (t, false, 1.0, 1.0);
  203. CTest<double> (t, false, 1.0, 1.0);
  204. CTest<string> (t, false, "", "");
  205. CTest<string> (t, false, "Hey", "Hey");
  206. CTest<string> (t, true, "Hey", "There");
  207. t = ExpressionType.GreaterThan;
  208. CTest<byte> (t, true, 5, 1);
  209. CTest<byte> (t, false, 10, 10);
  210. CTest<sbyte> (t, false, 1, 5);
  211. CTest<sbyte> (t, false, 1, 1);
  212. CTest<int> (t, false, 1, 1);
  213. CTest<uint> (t, true, 1, 0);
  214. CTest<ulong> (t, true, Int64.MaxValue, 0);
  215. CTest<double> (t, false, 1.0, 1.0);
  216. CTest<double> (t, false, 1.0, 1.0);
  217. t = ExpressionType.LessThan;
  218. CTest<byte> (t, false, 5, 1);
  219. CTest<byte> (t, false, 10, 10);
  220. CTest<sbyte> (t, true, 1, 5);
  221. CTest<sbyte> (t, false, 1, 1);
  222. CTest<int> (t, false, 1, 1);
  223. CTest<uint> (t, false, 1, 0);
  224. CTest<ulong> (t, false, Int64.MaxValue, 0);
  225. CTest<double> (t, false, 1.0, 1.0);
  226. CTest<double> (t, false, 1.0, 1.0);
  227. t = ExpressionType.GreaterThanOrEqual;
  228. CTest<byte> (t, true, 5, 1);
  229. CTest<byte> (t, true, 10, 10);
  230. CTest<sbyte> (t, false, 1, 5);
  231. CTest<sbyte> (t, true, 1, 1);
  232. CTest<int> (t, true, 1, 1);
  233. CTest<uint> (t, true, 1, 0);
  234. CTest<ulong> (t, true, Int64.MaxValue, 0);
  235. CTest<double> (t, true, 1.0, 1.0);
  236. CTest<double> (t, true, 1.0, 1.0);
  237. t = ExpressionType.LessThanOrEqual;
  238. CTest<byte> (t, false, 5, 1);
  239. CTest<byte> (t, true, 10, 10);
  240. CTest<sbyte> (t, true, 1, 5);
  241. CTest<sbyte> (t, true, 1, 1);
  242. CTest<int> (t, true, 1, 1);
  243. CTest<uint> (t, false, 1, 0);
  244. CTest<ulong> (t, false, Int64.MaxValue, 0);
  245. CTest<double> (t, true, 1.0, 1.0);
  246. CTest<double> (t, true, 1.0, 1.0);
  247. }
  248. [Test]
  249. public void MakeArrayIndex ()
  250. {
  251. var array = Expression.Constant (new int [] { 1, 2 }, typeof (int []));
  252. var index = Expression.Constant (1);
  253. var array_index = Expression.MakeBinary (
  254. ExpressionType.ArrayIndex,
  255. array,
  256. index);
  257. Assert.AreEqual (ExpressionType.ArrayIndex, array_index.NodeType);
  258. }
  259. }
  260. }