ea73b57dd5d467cf8e51cad0055561f8eb9ff7f5
[mono.git] / mcs / class / System.Core / Test / System.Linq.Expressions / ExpressionTest_MakeBinary.cs
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 <miguel@novell.com>
21 //
22 using System;
23 using System.Reflection;
24 using System.Linq;
25 using System.Linq.Expressions;
26 using NUnit.Framework;
27
28 namespace MonoTests.System.Linq.Expressions
29 {
30         [TestFixture]
31         public class ExpressionTest_MakeBinary {
32
33                 public static int GoodMethod (string a, double d)
34                 {
35                         return 1;
36                 }
37
38                 public static int BadMethodSig_1 ()
39                 {
40                         return 1;
41                 }
42
43                 public static int BadMethodSig_2 (int a)
44                 {
45                         return 1;
46                 }
47
48                 public static int BadMethodSig_3 (int a, int b, int c)
49                 {
50                         return 1;
51                 }
52
53                 static MethodInfo GM (string n)
54                 {
55                         MethodInfo [] methods = typeof (ExpressionTest_MakeBinary).GetMethods (
56                                 BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
57
58                         foreach (MethodInfo m in methods)
59                                 if (m.Name == n)
60                                         return m;
61
62                         throw new Exception (String.Format ("Method {0} not found", n));
63                 }
64
65                 [Test]
66                 public void MethodChecks ()
67                 {
68                         Expression left = Expression.Constant ("");
69                         Expression right = Expression.Constant (1.0);
70
71                         BinaryExpression r = Expression.Add (left, right, GM ("GoodMethod"));
72                         Assert.AreEqual (r.Type, typeof (int));
73                 }
74
75                 [Test]
76                 [ExpectedException(typeof (ArgumentException))]
77                 public void MethodCheck_BadArgs ()
78                 {
79                         Expression left = Expression.Constant ("");
80                         Expression right = Expression.Constant (1.0);
81
82                         Expression.Add (left, right, GM ("BadMethodSig_1"));
83                 }
84
85                 [Test]
86                 [ExpectedException(typeof (ArgumentException))]
87                 public void MethodCheck_BadArgs2 ()
88                 {
89                         Expression left = Expression.Constant ("");
90                         Expression right = Expression.Constant (1.0);
91
92                         Expression.Add (left, right, GM ("BadMethodSig_2"));
93                 }
94
95                 [Test]
96                 [ExpectedException(typeof (ArgumentException))]
97                 public void MethodCheck_BadArgs3 ()
98                 {
99                         Expression left = Expression.Constant ("");
100                         Expression right = Expression.Constant (1.0);
101
102                         Expression.Add (left, right, GM ("BadMethodSig_3"));
103                 }
104
105                 static void PassInt (ExpressionType nt)
106                 {
107                         Expression left = Expression.Constant (1);
108                         Expression right = Expression.Constant (1);
109
110                         Expression.MakeBinary (nt, left, right);
111                 }
112
113                 static void FailInt (ExpressionType nt)
114                 {
115                         Expression left = Expression.Constant (1);
116                         Expression right = Expression.Constant (1);
117
118                         try {
119                                 Expression.MakeBinary (nt, left, right);
120                         } catch (ArgumentException) {
121                                 return;
122                         } catch (InvalidOperationException) {
123                                 return;
124                         }
125                         // If we get here, there was an error
126                         Assert.Fail ("FailInt failed while creating an {0}", nt);
127                 }
128
129                 //
130                 // Checks that we complain on the proper ExpressionTypes
131                 //
132                 [Test]
133                 public void TestBinaryCtor ()
134                 {
135                         PassInt (ExpressionType.Add);
136                         PassInt (ExpressionType.AddChecked);
137                         PassInt (ExpressionType.And);
138                         PassInt (ExpressionType.Divide);
139                         PassInt (ExpressionType.Equal);
140                         PassInt (ExpressionType.ExclusiveOr);
141                         PassInt (ExpressionType.GreaterThan);
142                         PassInt (ExpressionType.GreaterThanOrEqual);
143                         PassInt (ExpressionType.LeftShift);
144                         PassInt (ExpressionType.LessThan);
145                         PassInt (ExpressionType.LessThanOrEqual);
146                         PassInt (ExpressionType.Multiply);
147                         PassInt (ExpressionType.MultiplyChecked);
148                         PassInt (ExpressionType.NotEqual);
149                         PassInt (ExpressionType.Or);
150                         PassInt (ExpressionType.Modulo);
151                         PassInt (ExpressionType.RightShift);
152                         PassInt (ExpressionType.Subtract);
153                         PassInt (ExpressionType.SubtractChecked);
154
155                         FailInt (ExpressionType.AndAlso);
156                         FailInt (ExpressionType.OrElse);
157                         FailInt (ExpressionType.Power);
158                         FailInt (ExpressionType.ArrayLength);
159                         FailInt (ExpressionType.ArrayIndex);
160                         FailInt (ExpressionType.Call);
161                         FailInt (ExpressionType.Coalesce);
162                         FailInt (ExpressionType.Conditional);
163                         FailInt (ExpressionType.Constant);
164                         FailInt (ExpressionType.Convert);
165                         FailInt (ExpressionType.ConvertChecked);
166                         FailInt (ExpressionType.Invoke);
167                         FailInt (ExpressionType.Lambda);
168                         FailInt (ExpressionType.ListInit);
169                         FailInt (ExpressionType.MemberAccess);
170                         FailInt (ExpressionType.MemberInit);
171                         FailInt (ExpressionType.Negate);
172                         FailInt (ExpressionType.UnaryPlus);
173                         FailInt (ExpressionType.NegateChecked);
174                         FailInt (ExpressionType.New);
175                         FailInt (ExpressionType.NewArrayInit);
176                         FailInt (ExpressionType.NewArrayBounds);
177                         FailInt (ExpressionType.Not);
178                         FailInt (ExpressionType.Parameter);
179                         FailInt (ExpressionType.Quote);
180                         FailInt (ExpressionType.TypeAs);
181                         FailInt (ExpressionType.TypeIs);
182                 }
183
184                 public T CodeGen<T> (Func<Expression, Expression, Expression> bin, T v1, T v2)
185                 {
186                         var lambda = Expression.Lambda<Func<T>> (bin (v1.ToConstant (), v2.ToConstant ())).Compile ();
187                         return lambda ();
188                 }
189
190                 [Test]
191                 public void TestOperations ()
192                 {
193                         Assert.AreEqual (30, CodeGen<int> ((a, b) => Expression.Add (a, b), 10, 20));
194                         Assert.AreEqual (-12, CodeGen<int> ((a, b) => Expression.Subtract (a, b), 11, 23));
195                         Assert.AreEqual (253, CodeGen<int> ((a, b) => Expression.Multiply (a, b), 11, 23));
196                         Assert.AreEqual (33, CodeGen<int> ((a, b) => Expression.Divide (a, b), 100, 3));
197                         Assert.AreEqual (100.0/3, CodeGen<double> ((a, b) => Expression.Divide (a, b), 100, 3));
198                 }
199
200                 void CTest<T> (ExpressionType node, bool r, T a, T b)
201                 {
202                         ParameterExpression pa = Expression.Parameter(typeof(T), "a");
203                         ParameterExpression pb = Expression.Parameter(typeof(T), "b");
204
205                         BinaryExpression p = Expression.MakeBinary (node, Expression.Constant (a), Expression.Constant(b));
206                         Expression<Func<T,T,bool>> pexpr = Expression.Lambda<Func<T,T,bool>> (
207                                 p, new ParameterExpression [] { pa, pb });
208
209                         Func<T,T,bool> compiled = pexpr.Compile ();
210                         Assert.AreEqual (r, compiled (a, b), String.Format ("{0} ({1},{2}) == {3}", node, a, b, r));
211                 }
212
213                 [Test]
214                 public void ComparisonTests ()
215                 {
216                         ExpressionType t = ExpressionType.Equal;
217
218                         CTest<byte>   (t, true,   10,  10);
219                         CTest<sbyte>  (t, false,   1,   5);
220                         CTest<sbyte>  (t, true,    1,   1);
221                         CTest<int>    (t, true,    1,   1);
222                         CTest<double> (t, true,  1.0, 1.0);
223                         CTest<string> (t, true,  "",  "");
224                         CTest<string> (t, true,  "Hey",  "Hey");
225                         CTest<string> (t, false,  "Hey",  "There");
226
227                         t = ExpressionType.NotEqual;
228
229                         CTest<byte>   (t, false,   10,  10);
230                         CTest<sbyte>  (t, true,   1,   5);
231                         CTest<sbyte>  (t, false,    1,   1);
232                         CTest<int>    (t, false,    1,   1);
233                         CTest<double> (t, false,  1.0, 1.0);
234                         CTest<double> (t, false,  1.0, 1.0);
235                         CTest<string> (t, false,  "",  "");
236                         CTest<string> (t, false,  "Hey",  "Hey");
237                         CTest<string> (t, true,  "Hey",  "There");
238
239                         t = ExpressionType.GreaterThan;
240                         CTest<byte>   (t, true,   5,  1);
241                         CTest<byte>   (t, false,   10,  10);
242                         CTest<sbyte>  (t, false,   1,   5);
243                         CTest<sbyte>  (t, false,    1,   1);
244                         CTest<int>    (t, false,    1,   1);
245                         CTest<uint>   (t, true,     1,   0);
246                         CTest<ulong>  (t, true,     Int64.MaxValue,  0);
247                         CTest<double> (t, false,  1.0, 1.0);
248                         CTest<double> (t, false,  1.0, 1.0);
249
250
251                         t = ExpressionType.LessThan;
252                         CTest<byte>   (t, false,   5,  1);
253                         CTest<byte>   (t, false,   10,  10);
254                         CTest<sbyte>  (t, true,   1,   5);
255                         CTest<sbyte>  (t, false,    1,   1);
256                         CTest<int>    (t, false,    1,   1);
257                         CTest<uint>   (t, false,     1,   0);
258                         CTest<ulong>  (t, false,     Int64.MaxValue,  0);
259                         CTest<double> (t, false,  1.0, 1.0);
260                         CTest<double> (t, false,  1.0, 1.0);
261
262                         t = ExpressionType.GreaterThanOrEqual;
263                         CTest<byte>   (t, true,   5,  1);
264                         CTest<byte>   (t, true,   10,  10);
265                         CTest<sbyte>  (t, false,   1,   5);
266                         CTest<sbyte>  (t, true,    1,   1);
267                         CTest<int>    (t, true,    1,   1);
268                         CTest<uint>   (t, true,     1,   0);
269                         CTest<ulong>  (t, true,     Int64.MaxValue,  0);
270                         CTest<double> (t, true,  1.0, 1.0);
271                         CTest<double> (t, true,  1.0, 1.0);
272
273
274                         t = ExpressionType.LessThanOrEqual;
275                         CTest<byte>   (t, false,   5,  1);
276                         CTest<byte>   (t, true,   10,  10);
277                         CTest<sbyte>  (t, true,   1,   5);
278                         CTest<sbyte>  (t, true,    1,   1);
279                         CTest<int>    (t, true,    1,   1);
280                         CTest<uint>   (t, false,     1,   0);
281                         CTest<ulong>  (t, false,     Int64.MaxValue,  0);
282                         CTest<double> (t, true,  1.0, 1.0);
283                         CTest<double> (t, true,  1.0, 1.0);
284
285                 }
286
287         }
288 }