Add [Category ("NotWorking")] to failing test.
[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 #if NET_4_0 && !MONOTOUCH
91                 [ExpectedException (typeof (ArgumentException))]
92 #else
93                 [ExpectedException (typeof (ArgumentNullException))]
94 #endif
95                 public void ArgInstanceNullForNonStaticMethod ()
96                 {
97                         Expression.Call (null, typeof (object).GetMethod ("ToString"));
98                 }
99
100                 [Test]
101                 [ExpectedException (typeof (ArgumentException))]
102                 public void InstanceTypeDoesntMatchMethodDeclaringType ()
103                 {
104 #if MOBILE
105                         // ensure that String.Intern won't be removed by the linker
106                         string s = String.Intern (String.Empty);
107 #endif
108                         Expression.Call (Expression.Constant (1), typeof (string).GetMethod ("Intern"));
109                 }
110
111                 [Test]
112                 [ExpectedException (typeof (ArgumentException))]
113                 public void MethodArgumentCountDoesnMatchParameterLength ()
114                 {
115                         Expression.Call (Expression.Constant (new object ()), typeof (object).GetMethod ("ToString"), Expression.Constant (new object ()));
116                 }
117
118                 public class Foo {
119                         public void Bar (string s)
120                         {
121                         }
122                 }
123
124                 [Test]
125                 [ExpectedException (typeof (ArgumentNullException))]
126                 public void MethodHasNullArgument ()
127                 {
128                         Expression.Call (Expression.New (typeof (Foo)), typeof (Foo).GetMethod ("Bar"), null as Expression);
129                 }
130
131                 [Test]
132                 [ExpectedException (typeof (ArgumentException))]
133                 public void MethodArgumentDoesntMatchParameterType ()
134                 {
135                         Expression.Call (Expression.New (typeof (Foo)), typeof (Foo).GetMethod ("Bar"), Expression.Constant (42));
136                 }
137
138                 [Test]
139                 public void CallToString ()
140                 {
141                         var call = Expression.Call (Expression.Constant (new object ()), typeof (object).GetMethod ("ToString"));
142                         Assert.AreEqual ("value(System.Object).ToString()", call.ToString ());
143                 }
144
145                 [Test]
146                 public void CallStringIsNullOrEmpty ()
147                 {
148                         var call = Expression.Call (null, typeof (string).GetMethod ("IsNullOrEmpty"), Expression.Constant (""));
149                         Assert.AreEqual ("IsNullOrEmpty(\"\")", call.ToString ());
150                 }
151
152                 [Test]
153                 [Category ("NotDotNet")] // http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=339351
154                 [ExpectedException (typeof (ArgumentException))]
155                 public void CallStaticMethodWithInstanceArgument ()
156                 {
157                         Expression.Call (
158                                 Expression.Parameter (GetType (), "t"),
159                                 GetType ().GetMethod ("Identity"),
160                                 Expression.Constant (null));
161                 }
162
163                 public static object Identity (object o)
164                 {
165                         return o;
166                 }
167
168                 [Test]
169                 public void CompileSimpleStaticCall ()
170                 {
171                         var p = Expression.Parameter (typeof (object), "o");
172                         var lambda = Expression.Lambda<Func<object, object>> (Expression.Call (GetType ().GetMethod ("Identity"), p), p);
173
174                         var i = lambda.Compile ();
175
176                         Assert.AreEqual (2, i (2));
177                         Assert.AreEqual ("Foo", i ("Foo"));
178                 }
179
180                 [Test]
181                 public void CompileSimpleInstanceCall ()
182                 {
183                         var p = Expression.Parameter (typeof (string), "p");
184                         var lambda = Expression.Lambda<Func<string, string>> (
185                                 Expression.Call (
186                                         p, typeof (string).GetMethod ("ToString", Type.EmptyTypes)),
187                                 p);
188
189                         var ts = lambda.Compile ();
190
191                         Assert.AreEqual ("foo", ts ("foo"));
192                         Assert.AreEqual ("bar", ts ("bar"));
193                 }
194
195                 [Test]
196                 [ExpectedException (typeof (InvalidOperationException))]
197                 public void CheckTypeArgsIsNotUsedForParameterLookup ()
198                 {
199                         Expression.Call (GetType (), "EineMethod", new [] { typeof (string), typeof (int) }, "foo".ToConstant (), 2.ToConstant ());
200                 }
201
202                 public static void EineGenericMethod<X, Y> (string foo, int bar)
203                 {
204                 }
205
206                 [Test]
207                 public void CheckTypeArgsIsUsedForGenericArguments ()
208                 {
209                         var m = Expression.Call (GetType (), "EineGenericMethod", new [] { typeof (string), typeof (int) }, "foo".ToConstant (), 2.ToConstant ());
210                         Assert.IsNotNull (m.Method);
211                         Assert.AreEqual ("Void EineGenericMethod[String,Int32](System.String, Int32)", m.Method.ToString ());
212                 }
213
214                 public struct EineStrukt {
215
216                         public string Foo;
217
218                         public EineStrukt (string foo)
219                         {
220                                 Foo = foo;
221                         }
222
223                         public string GimmeFoo ()
224                         {
225                                 return Foo;
226                         }
227                 }
228
229                 [Test]
230                 public void CallMethodOnStruct ()
231                 {
232                         var param = Expression.Parameter (typeof (EineStrukt), "s");
233                         var foo = Expression.Lambda<Func<EineStrukt, string>> (
234                                 Expression.Call (param, typeof (EineStrukt).GetMethod ("GimmeFoo")), param).Compile ();
235
236                         var s = new EineStrukt ("foo");
237                         Assert.AreEqual ("foo", foo (s));
238                 }
239
240                 public static int OneStaticMethod ()
241                 {
242                         return 42;
243                 }
244
245                 [Test]
246                 [Category ("NotDotNet")] // http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=339351
247                 [ExpectedException (typeof (ArgumentException))]
248                 public void CallStaticMethodOnNonSenseInstanceExpression ()
249                 {
250                         Expression.Call (
251                                 Expression.Constant ("la la la"),
252                                 this.GetType ().GetMethod ("OneStaticMethod"));
253                 }
254
255                 public static int DoSomethingWith (ref int a)
256                 {
257                         return a + 4;
258                 }
259
260                 public static string DoAnotherThing (ref int a, string s)
261                 {
262                         return s + a;
263                 }
264
265                 [Test]
266                 public void CallStaticMethodWithRefParameter ()
267                 {
268                         var p = Expression.Parameter (typeof (int), "i");
269
270                         var c = Expression.Lambda<Func<int, int>> (
271                                 Expression.Call (GetType ().GetMethod ("DoSomethingWith"), p), p).Compile ();
272
273                         Assert.AreEqual (42, c (38));
274                 }
275
276                 [Test]
277                 public void CallStaticMethodWithRefParameterAndOtherParameter ()
278                 {
279                         var i = Expression.Parameter (typeof (int), "i");
280                         var s = Expression.Parameter (typeof (string), "s");
281
282                         var lamda = Expression.Lambda<Func<int, string, string>> (
283                                 Expression.Call (GetType ().GetMethod ("DoAnotherThing"), i, s), i, s).Compile ();
284
285                         Assert.AreEqual ("foo42", lamda (42, "foo"));
286                 }
287
288                 public static int Bang (Expression i)
289                 {
290                         return (int) (i as ConstantExpression).Value;
291                 }
292 #if !NET_4_0 // dlr bug 5875
293                 [Test]
294                 public void CallMethodWithExpressionParameter ()
295                 {
296                         var call = Expression.Call (GetType ().GetMethod ("Bang"), Expression.Constant (42));
297                         Assert.AreEqual (ExpressionType.Quote, call.Arguments [0].NodeType);
298
299                         var l = Expression.Lambda<Func<int>> (call).Compile ();
300
301                         Assert.AreEqual (42, l ());
302                 }
303 #endif
304                 static bool fout_called = false;
305
306                 public static int FooOut (out int x)
307                 {
308                         fout_called = true;
309                         return x = 0;
310                 }
311
312                 [Test]
313                 public void Connect282729 ()
314                 {
315                         // test from https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=282729
316
317                         var p = Expression.Parameter (typeof (int), "p");
318                         var lambda = Expression.Lambda<Func<int, int>> (
319                                 Expression.Call (
320                                         GetType ().GetMethod ("FooOut"),
321                                         Expression.ArrayIndex(
322                                                 Expression.NewArrayBounds (
323                                                         typeof(int),
324                                                         1.ToConstant ()),
325                                                 0.ToConstant ())),
326                                 p).Compile ();
327
328                         Assert.AreEqual (0, lambda (0));
329                         Assert.IsTrue (fout_called);
330                 }
331
332                 public static int FooOut2 (out int x)
333                 {
334                         x = 2;
335                         return 3;
336                 }
337
338                 [Test]
339                 [Category ("NotWorking")]
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                 public void Connect297597 ()
363                 {
364                         // test from https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=297597
365
366                         var strings = new string [1];
367
368                         var lambda = Expression.Lambda<Action> (
369                                 Expression.Call (
370                                         GetType ().GetMethod ("FooRef"),
371                                         Expression.ArrayIndex (
372                                                 Expression.Constant (strings), 0.ToConstant ()))).Compile ();
373
374                         lambda ();
375                 }
376
377                 [Test]
378 #if MONOTOUCH
379                 [Category ("NotWorking")]
380 #endif
381                 [Category ("NotDotNet")] // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=319190
382                 public void Connect319190 ()
383                 {
384                         var lambda = Expression.Lambda<Func<bool>> (
385                                 Expression.TypeIs (
386                                         Expression.New (typeof (TypedReference)),
387                                         typeof (object))).Compile ();
388
389                         Assert.IsTrue (lambda ());
390                 }
391
392                 public static int Truc ()
393                 {
394                         return 42;
395                 }
396
397                 [Test]
398                 public void Connect282702 ()
399                 {
400                         var lambda = Expression.Lambda<Func<Func<int>>> (
401                                 Expression.Convert (
402                                         Expression.Call (
403                                                 typeof (Delegate).GetMethod ("CreateDelegate", new [] { typeof (Type), typeof (object), typeof (MethodInfo) }),
404                                                 Expression.Constant (typeof (Func<int>), typeof (Type)),
405                                                 Expression.Constant (null, typeof (object)),
406                                                 Expression.Constant (GetType ().GetMethod ("Truc"))),
407                                         typeof (Func<int>))).Compile ();
408
409                         Assert.AreEqual (42, lambda ().Invoke ());
410                 }
411
412                 [Test]
413                 public void CallQueryableWhere ()
414                 {
415                         var queryable = new [] { 1, 2, 3 }.AsQueryable ();
416
417                         var parameter = Expression.Parameter (typeof (int), "i");
418                         var lambda = Expression.Lambda<Func<int, bool>> (
419                                 Expression.LessThan (parameter, Expression.Constant (2)),
420                                 parameter);
421
422                         var selector = Expression.Quote (lambda);
423
424                         var call = Expression.Call (
425                                 typeof (Queryable),
426                                 "Where",
427                                 new [] { typeof (int) },
428                                 queryable.Expression,
429                                 selector);
430
431                         Assert.IsNotNull (call);
432                         Assert.IsNotNull (call.Method);
433                 }
434
435                 [Test]
436                 public void CallAsQueryable () // #537768
437                 {
438                         var constant = Expression.Constant (
439                                 new List<string> (),
440                                 typeof (IEnumerable<string>));
441
442                         var call = Expression.Call (
443                                 typeof (Queryable),
444                                 "AsQueryable",
445                                 new [] { typeof (string) },
446                                 constant);
447
448                         Assert.IsNotNull (call);
449                         Assert.AreEqual (1, call.Arguments.Count);
450                         Assert.AreEqual (constant, call.Arguments [0]);
451
452                         var method = call.Method;
453
454                         Assert.AreEqual ("AsQueryable", method.Name);
455                         Assert.IsTrue (method.IsGenericMethod);
456                         Assert.AreEqual (typeof (string), method.GetGenericArguments () [0]);
457                 }
458
459
460                 [Test]
461                 public void CallQueryableSelect () // #536637
462                 {
463                         var parameter = Expression.Parameter (typeof (string), "s");
464                         var string_length = Expression.Property (parameter, typeof (string).GetProperty ("Length"));
465                         var lambda = Expression.Lambda (string_length, parameter);
466
467                         var strings = new [] { "1", "22", "333" };
468
469                         var call = Expression.Call (
470                                 typeof (Queryable),
471                                 "Select",
472                                 new [] { typeof (string), typeof (int) },
473                                 Expression.Constant (strings.AsQueryable ()),
474                                 lambda);
475
476                         Assert.IsNotNull (call);
477
478                         var method = call.Method;
479
480                         Assert.AreEqual ("Select", method.Name);
481                         Assert.IsTrue (method.IsGenericMethod);
482                         Assert.AreEqual (typeof (string), method.GetGenericArguments () [0]);
483                         Assert.AreEqual (typeof (int), method.GetGenericArguments () [1]);
484                 }
485
486                 [Test]
487 #if MONOTOUCH
488                 [Category ("NotWorking")]
489 #endif
490                 public void CallNullableGetValueOrDefault () // #568989
491                 {
492                         var value = Expression.Parameter (typeof (int?), "value");
493                         var default_parameter = Expression.Parameter (typeof (int), "default");
494
495                         var getter = Expression.Lambda<Func<int?, int, int>> (
496                                 Expression.Call (
497                                         value,
498                                         "GetValueOrDefault",
499                                         Type.EmptyTypes,
500                                         default_parameter),
501                                 value,
502                                 default_parameter).Compile ();
503
504                         Assert.AreEqual (2, getter (null, 2));
505                         Assert.AreEqual (4, getter (4, 2));
506                 }
507
508                 [Test]
509                 public void CallToStringOnEnum () // #625367
510                 {
511                         var lambda = Expression.Lambda<Func<string>> (
512                                 Expression.Call (
513                                         Expression.Constant (TypeCode.Boolean, typeof (TypeCode)),
514                                         typeof (object).GetMethod ("ToString"))).Compile ();
515
516                         Assert.AreEqual ("Boolean", lambda ());
517                 }
518
519                 public static void AcceptsIEnumerable(IEnumerable<object> o)
520                 {
521                 }
522
523                 [Test]
524                 public void CallIQueryableMethodWithNewArrayBoundExpression () // #2304
525                 {
526                         Expression.Call (
527                                 GetType ().GetMethod ("AcceptsIEnumerable", BindingFlags.Public | BindingFlags.Static),
528                                 Expression.NewArrayBounds (typeof (object), Expression.Constant (0)));
529                 }
530         }
531 }