Merge pull request #2274 from esdrubal/udpclientreceive
[mono.git] / mcs / class / System.Core / Test / System.Linq.Expressions / ExpressionTest_Call.cs
1 //
2 // ExpressionTest_Call.cs
3 //
4 // Author:
5 //   Federico Di Gregorio <fog@initd.org>
6 //   Jb Evain (jbevain@novell.com)
7 //
8 // (C) 2008 Novell, Inc. (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System;
31 using System.Reflection;
32 using System.Collections.Generic;
33 using System.Linq;
34 using System.Linq.Expressions;
35 using NUnit.Framework;
36
37 namespace MonoTests.System.Linq.Expressions {
38
39         [TestFixture]
40         public class ExpressionTest_Call {
41
42                 [Test]
43                 [ExpectedException (typeof (ArgumentNullException))]
44                 public void Arg1Null ()
45                 {
46                         Expression.Call ((Type)null, "TestMethod", null, Expression.Constant (1));
47                 }
48
49                 [Test]
50                 [ExpectedException (typeof (ArgumentNullException))]
51                 public void Arg2Null ()
52                 {
53                         Expression.Call (typeof (MemberClass), null, null, Expression.Constant (1));
54                 }
55
56                 [Test]
57                 [ExpectedException (typeof (InvalidOperationException))]
58                 public void Arg4WrongType ()
59                 {
60                         Expression.Call (typeof (MemberClass), "StaticMethod", null, Expression.Constant (true));
61                 }
62
63                 [Test]
64                 [ExpectedException (typeof (InvalidOperationException))]
65                 public void InstanceMethod ()
66                 {
67                         Expression.Call (typeof (MemberClass), "TestMethod", null, Expression.Constant (1));
68                 }
69
70                 [Test]
71                 public void StaticMethod ()
72                 {
73                         Expression.Call (typeof (MemberClass), "StaticMethod", null, Expression.Constant (1));
74                 }
75
76                 [Test]
77                 public void StaticGenericMethod ()
78                 {
79                         Expression.Call (typeof (MemberClass), "StaticGenericMethod", new [] { typeof (int) }, Expression.Constant (1));
80                 }
81
82                 [Test]
83                 [ExpectedException (typeof (ArgumentNullException))]
84                 public void ArgMethodNull ()
85                 {
86                         Expression.Call (Expression.Constant (new object ()), null);
87                 }
88
89                 [Test]
90                 [ExpectedException (typeof (ArgumentException))]
91                 public void ArgInstanceNullForNonStaticMethod ()
92                 {
93                         Expression.Call (null, typeof (object).GetMethod ("ToString"));
94                 }
95
96                 [Test]
97                 [ExpectedException (typeof (ArgumentException))]
98                 public void InstanceTypeDoesntMatchMethodDeclaringType ()
99                 {
100 #if MOBILE
101                         // ensure that String.Intern won't be removed by the linker
102                         string s = String.Intern (String.Empty);
103 #endif
104                         Expression.Call (Expression.Constant (1), typeof (string).GetMethod ("Intern"));
105                 }
106
107                 [Test]
108                 [ExpectedException (typeof (ArgumentException))]
109                 public void MethodArgumentCountDoesnMatchParameterLength ()
110                 {
111                         Expression.Call (Expression.Constant (new object ()), typeof (object).GetMethod ("ToString"), Expression.Constant (new object ()));
112                 }
113
114                 public class Foo {
115                         public void Bar (string s)
116                         {
117                         }
118                 }
119
120                 [Test]
121                 [ExpectedException (typeof (ArgumentNullException))]
122                 public void MethodHasNullArgument ()
123                 {
124                         Expression.Call (Expression.New (typeof (Foo)), typeof (Foo).GetMethod ("Bar"), null as Expression);
125                 }
126
127                 [Test]
128                 [ExpectedException (typeof (ArgumentException))]
129                 public void MethodArgumentDoesntMatchParameterType ()
130                 {
131                         Expression.Call (Expression.New (typeof (Foo)), typeof (Foo).GetMethod ("Bar"), Expression.Constant (42));
132                 }
133
134                 [Test]
135                 public void CallToString ()
136                 {
137                         var call = Expression.Call (Expression.Constant (new object ()), typeof (object).GetMethod ("ToString"));
138                         Assert.AreEqual ("value(System.Object).ToString()", call.ToString ());
139                 }
140
141                 [Test]
142                 public void CallStringIsNullOrEmpty ()
143                 {
144                         var call = Expression.Call (null, typeof (string).GetMethod ("IsNullOrEmpty"), Expression.Constant (""));
145                         Assert.AreEqual ("IsNullOrEmpty(\"\")", call.ToString ());
146                 }
147
148                 [Test]
149                 [Category ("NotDotNet")] // http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=339351
150                 [ExpectedException (typeof (ArgumentException))]
151                 public void CallStaticMethodWithInstanceArgument ()
152                 {
153                         Expression.Call (
154                                 Expression.Parameter (GetType (), "t"),
155                                 GetType ().GetMethod ("Identity"),
156                                 Expression.Constant (null));
157                 }
158
159                 public static object Identity (object o)
160                 {
161                         return o;
162                 }
163
164                 [Test]
165                 public void CompileSimpleStaticCall ()
166                 {
167                         var p = Expression.Parameter (typeof (object), "o");
168                         var lambda = Expression.Lambda<Func<object, object>> (Expression.Call (GetType ().GetMethod ("Identity"), p), p);
169
170                         var i = lambda.Compile ();
171
172                         Assert.AreEqual (2, i (2));
173                         Assert.AreEqual ("Foo", i ("Foo"));
174                 }
175
176                 [Test]
177                 public void CompileSimpleInstanceCall ()
178                 {
179                         var p = Expression.Parameter (typeof (string), "p");
180                         var lambda = Expression.Lambda<Func<string, string>> (
181                                 Expression.Call (
182                                         p, typeof (string).GetMethod ("ToString", Type.EmptyTypes)),
183                                 p);
184
185                         var ts = lambda.Compile ();
186
187                         Assert.AreEqual ("foo", ts ("foo"));
188                         Assert.AreEqual ("bar", ts ("bar"));
189                 }
190
191                 [Test]
192                 [ExpectedException (typeof (InvalidOperationException))]
193                 public void CheckTypeArgsIsNotUsedForParameterLookup ()
194                 {
195                         Expression.Call (GetType (), "EineMethod", new [] { typeof (string), typeof (int) }, "foo".ToConstant (), 2.ToConstant ());
196                 }
197
198                 public static void EineGenericMethod<X, Y> (string foo, int bar)
199                 {
200                 }
201
202                 [Test]
203                 public void CheckTypeArgsIsUsedForGenericArguments ()
204                 {
205                         var m = Expression.Call (GetType (), "EineGenericMethod", new [] { typeof (string), typeof (int) }, "foo".ToConstant (), 2.ToConstant ());
206                         Assert.IsNotNull (m.Method);
207                         Assert.AreEqual ("Void EineGenericMethod[String,Int32](System.String, Int32)", m.Method.ToString ());
208                 }
209
210                 public struct EineStrukt {
211
212                         public string Foo;
213
214                         public EineStrukt (string foo)
215                         {
216                                 Foo = foo;
217                         }
218
219                         public string GimmeFoo ()
220                         {
221                                 return Foo;
222                         }
223                 }
224
225                 [Test]
226                 [Category ("NotWorkingInterpreter")]
227                 public void CallMethodOnStruct ()
228                 {
229                         var param = Expression.Parameter (typeof (EineStrukt), "s");
230                         var foo = Expression.Lambda<Func<EineStrukt, string>> (
231                                 Expression.Call (param, typeof (EineStrukt).GetMethod ("GimmeFoo")), param).Compile ();
232
233                         var s = new EineStrukt ("foo");
234                         Assert.AreEqual ("foo", foo (s));
235                 }
236
237                 public static int OneStaticMethod ()
238                 {
239                         return 42;
240                 }
241
242                 [Test]
243                 public void CallMethodOnDateTime ()
244                 {
245                         var left = Expression.Call (Expression.Constant (DateTime.Now), typeof(DateTime).GetMethod ("AddDays"), Expression.Constant (-5.0));
246                         var right = Expression.Constant (DateTime.Today.AddDays (1));
247                         var expr = Expression.GreaterThan (left, right);
248
249                         var eq = Expression.Lambda<Func<bool>> (expr).Compile ();
250                         Assert.IsFalse (eq ());
251                 }
252
253                 [Test]
254                 [Category ("NotDotNet")] // http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=339351
255                 [ExpectedException (typeof (ArgumentException))]
256                 public void CallStaticMethodOnNonSenseInstanceExpression ()
257                 {
258                         Expression.Call (
259                                 Expression.Constant ("la la la"),
260                                 this.GetType ().GetMethod ("OneStaticMethod"));
261                 }
262
263                 public static int DoSomethingWith (ref int a)
264                 {
265                         return a + 4;
266                 }
267
268                 public static string DoAnotherThing (ref int a, string s)
269                 {
270                         return s + a;
271                 }
272
273                 [Test]
274                 [Category ("NotWorkingInterpreter")]
275                 public void CallStaticMethodWithRefParameter ()
276                 {
277                         var p = Expression.Parameter (typeof (int), "i");
278
279                         var c = Expression.Lambda<Func<int, int>> (
280                                 Expression.Call (GetType ().GetMethod ("DoSomethingWith"), p), p).Compile ();
281
282                         Assert.AreEqual (42, c (38));
283                 }
284
285                 [Test]
286                 [Category ("NotWorkingInterpreter")]
287                 public void CallStaticMethodWithRefParameterAndOtherParameter ()
288                 {
289                         var i = Expression.Parameter (typeof (int), "i");
290                         var s = Expression.Parameter (typeof (string), "s");
291
292                         var lamda = Expression.Lambda<Func<int, string, string>> (
293                                 Expression.Call (GetType ().GetMethod ("DoAnotherThing"), i, s), i, s).Compile ();
294
295                         Assert.AreEqual ("foo42", lamda (42, "foo"));
296                 }
297
298                 public static int Bang (Expression i)
299                 {
300                         return (int) (i as ConstantExpression).Value;
301                 }
302                 static bool fout_called = false;
303
304                 public static int FooOut (out int x)
305                 {
306                         fout_called = true;
307                         return x = 0;
308                 }
309
310                 [Test]
311                 [Category ("NotWorkingInterpreter")]
312                 public void Connect282729 ()
313                 {
314                         // test from https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=282729
315
316                         var p = Expression.Parameter (typeof (int), "p");
317                         var lambda = Expression.Lambda<Func<int, int>> (
318                                 Expression.Call (
319                                         GetType ().GetMethod ("FooOut"),
320                                         Expression.ArrayIndex(
321                                                 Expression.NewArrayBounds (
322                                                         typeof(int),
323                                                         1.ToConstant ()),
324                                                 0.ToConstant ())),
325                                 p).Compile ();
326
327                         Assert.AreEqual (0, lambda (0));
328                         Assert.IsTrue (fout_called);
329                 }
330
331                 public static int FooOut2 (out int x)
332                 {
333                         x = 2;
334                         return 3;
335                 }
336
337                 [Test]
338                 [Category ("NotWorking")]
339                 [Category ("NotWorkingInterpreter")]
340                 public void Connect290278 ()
341                 {
342                         // test from https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=290278
343
344                         var p = Expression.Parameter (typeof (int [,]), "p");
345                         var lambda = Expression.Lambda<Func<int [,], int>> (
346                                 Expression.Call (
347                                         GetType ().GetMethod ("FooOut2"),
348                                         Expression.ArrayIndex (p, 0.ToConstant (), 0.ToConstant ())),
349                                 p).Compile ();
350
351                         int [,] data = { { 1 } };
352
353                         Assert.AreEqual (3, lambda (data));
354                         Assert.AreEqual (2, data [0, 0]);
355                 }
356
357                 public static void FooRef (ref string s)
358                 {
359                 }
360
361                 [Test]
362                 [Category ("NotWorkingInterpreter")]
363                 public void Connect297597 ()
364                 {
365                         // test from https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=297597
366
367                         var strings = new string [1];
368
369                         var lambda = Expression.Lambda<Action> (
370                                 Expression.Call (
371                                         GetType ().GetMethod ("FooRef"),
372                                         Expression.ArrayIndex (
373                                                 Expression.Constant (strings), 0.ToConstant ()))).Compile ();
374
375                         lambda ();
376                 }
377
378                 [Test]
379                 [Category ("NotDotNet")] // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=319190
380                 public void Connect319190 ()
381                 {
382                         var lambda = Expression.Lambda<Func<bool>> (
383                                 Expression.TypeIs (
384                                         Expression.New (typeof (TypedReference)),
385                                         typeof (object))).Compile ();
386
387                         Assert.IsTrue (lambda ());
388                 }
389
390                 public static int Truc ()
391                 {
392                         return 42;
393                 }
394
395                 [Test]
396                 public void Connect282702 ()
397                 {
398                         var lambda = Expression.Lambda<Func<Func<int>>> (
399                                 Expression.Convert (
400                                         Expression.Call (
401                                                 typeof (Delegate).GetMethod ("CreateDelegate", new [] { typeof (Type), typeof (object), typeof (MethodInfo) }),
402                                                 Expression.Constant (typeof (Func<int>), typeof (Type)),
403                                                 Expression.Constant (null, typeof (object)),
404                                                 Expression.Constant (GetType ().GetMethod ("Truc"))),
405                                         typeof (Func<int>))).Compile ();
406
407                         Assert.AreEqual (42, lambda ().Invoke ());
408                 }
409
410                 [Test]
411                 public void CallQueryableWhere ()
412                 {
413                         var queryable = new [] { 1, 2, 3 }.AsQueryable ();
414
415                         var parameter = Expression.Parameter (typeof (int), "i");
416                         var lambda = Expression.Lambda<Func<int, bool>> (
417                                 Expression.LessThan (parameter, Expression.Constant (2)),
418                                 parameter);
419
420                         var selector = Expression.Quote (lambda);
421
422                         var call = Expression.Call (
423                                 typeof (Queryable),
424                                 "Where",
425                                 new [] { typeof (int) },
426                                 queryable.Expression,
427                                 selector);
428
429                         Assert.IsNotNull (call);
430                         Assert.IsNotNull (call.Method);
431                 }
432
433                 [Test]
434                 public void CallAsQueryable () // #537768
435                 {
436                         var constant = Expression.Constant (
437                                 new List<string> (),
438                                 typeof (IEnumerable<string>));
439
440                         var call = Expression.Call (
441                                 typeof (Queryable),
442                                 "AsQueryable",
443                                 new [] { typeof (string) },
444                                 constant);
445
446                         Assert.IsNotNull (call);
447                         Assert.AreEqual (1, call.Arguments.Count);
448                         Assert.AreEqual (constant, call.Arguments [0]);
449
450                         var method = call.Method;
451
452                         Assert.AreEqual ("AsQueryable", method.Name);
453                         Assert.IsTrue (method.IsGenericMethod);
454                         Assert.AreEqual (typeof (string), method.GetGenericArguments () [0]);
455                 }
456
457
458                 [Test]
459                 public void CallQueryableSelect () // #536637
460                 {
461                         var parameter = Expression.Parameter (typeof (string), "s");
462                         var string_length = Expression.Property (parameter, typeof (string).GetProperty ("Length"));
463                         var lambda = Expression.Lambda (string_length, parameter);
464
465                         var strings = new [] { "1", "22", "333" };
466
467                         var call = Expression.Call (
468                                 typeof (Queryable),
469                                 "Select",
470                                 new [] { typeof (string), typeof (int) },
471                                 Expression.Constant (strings.AsQueryable ()),
472                                 lambda);
473
474                         Assert.IsNotNull (call);
475
476                         var method = call.Method;
477
478                         Assert.AreEqual ("Select", method.Name);
479                         Assert.IsTrue (method.IsGenericMethod);
480                         Assert.AreEqual (typeof (string), method.GetGenericArguments () [0]);
481                         Assert.AreEqual (typeof (int), method.GetGenericArguments () [1]);
482                 }
483
484                 [Test]
485                 [Category ("NotWorkingInterpreter")]
486                 public void CallNullableGetValueOrDefault () // #568989
487                 {
488                         var value = Expression.Parameter (typeof (int?), "value");
489                         var default_parameter = Expression.Parameter (typeof (int), "default");
490
491                         var getter = Expression.Lambda<Func<int?, int, int>> (
492                                 Expression.Call (
493                                         value,
494                                         "GetValueOrDefault",
495                                         Type.EmptyTypes,
496                                         default_parameter),
497                                 value,
498                                 default_parameter).Compile ();
499
500                         Assert.AreEqual (2, getter (null, 2));
501                         Assert.AreEqual (4, getter (4, 2));
502                 }
503
504                 [Test]
505                 public void CallToStringOnEnum () // #625367
506                 {
507                         var lambda = Expression.Lambda<Func<string>> (
508                                 Expression.Call (
509                                         Expression.Constant (TypeCode.Boolean, typeof (TypeCode)),
510                                         typeof (object).GetMethod ("ToString"))).Compile ();
511
512                         Assert.AreEqual ("Boolean", lambda ());
513                 }
514
515                 public static void AcceptsIEnumerable(IEnumerable<object> o)
516                 {
517                 }
518
519                 [Test]
520                 public void CallIQueryableMethodWithNewArrayBoundExpression () // #2304
521                 {
522                         Expression.Call (
523                                 GetType ().GetMethod ("AcceptsIEnumerable", BindingFlags.Public | BindingFlags.Static),
524                                 Expression.NewArrayBounds (typeof (object), Expression.Constant (0)));
525                 }
526         }
527 }