2 // ExpressionTest_Call.cs
5 // Federico Di Gregorio <fog@initd.org>
6 // Jb Evain (jbevain@novell.com)
8 // (C) 2008 Novell, Inc. (http://www.novell.com)
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:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
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.
31 using System.Reflection;
32 using System.Reflection.Emit;
33 using System.Collections.Generic;
35 using System.Linq.Expressions;
36 using NUnit.Framework;
38 namespace MonoTests.System.Linq.Expressions {
41 public class ExpressionTest_Call {
44 [ExpectedException (typeof (ArgumentNullException))]
45 public void Arg1Null ()
47 Expression.Call ((Type)null, "TestMethod", null, Expression.Constant (1));
51 [ExpectedException (typeof (ArgumentNullException))]
52 public void Arg2Null ()
54 Expression.Call (typeof (MemberClass), null, null, Expression.Constant (1));
58 [ExpectedException (typeof (InvalidOperationException))]
59 public void Arg4WrongType ()
61 Expression.Call (typeof (MemberClass), "StaticMethod", null, Expression.Constant (true));
65 [ExpectedException (typeof (InvalidOperationException))]
66 public void InstanceMethod ()
68 Expression.Call (typeof (MemberClass), "TestMethod", null, Expression.Constant (1));
72 public void StaticMethod ()
74 Expression.Call (typeof (MemberClass), "StaticMethod", null, Expression.Constant (1));
78 public void StaticGenericMethod ()
80 Expression.Call (typeof (MemberClass), "StaticGenericMethod", new [] { typeof (int) }, Expression.Constant (1));
84 [ExpectedException (typeof (ArgumentNullException))]
85 public void ArgMethodNull ()
87 Expression.Call (Expression.Constant (new object ()), null);
91 [ExpectedException (typeof (ArgumentException))]
92 public void ArgInstanceNullForNonStaticMethod ()
94 Expression.Call (null, typeof (object).GetMethod ("ToString"));
98 [ExpectedException (typeof (ArgumentException))]
99 public void InstanceTypeDoesntMatchMethodDeclaringType ()
102 // ensure that String.Intern won't be removed by the linker
103 string s = String.Intern (String.Empty);
105 Expression.Call (Expression.Constant (1), typeof (string).GetMethod ("Intern"));
109 [ExpectedException (typeof (ArgumentException))]
110 public void MethodArgumentCountDoesnMatchParameterLength ()
112 Expression.Call (Expression.Constant (new object ()), typeof (object).GetMethod ("ToString"), Expression.Constant (new object ()));
116 public void Bar (string s)
122 [ExpectedException (typeof (ArgumentNullException))]
123 public void MethodHasNullArgument ()
125 Expression.Call (Expression.New (typeof (Foo)), typeof (Foo).GetMethod ("Bar"), null as Expression);
129 [ExpectedException (typeof (ArgumentException))]
130 public void MethodArgumentDoesntMatchParameterType ()
132 Expression.Call (Expression.New (typeof (Foo)), typeof (Foo).GetMethod ("Bar"), Expression.Constant (42));
136 public void CallToString ()
138 var call = Expression.Call (Expression.Constant (new object ()), typeof (object).GetMethod ("ToString"));
139 Assert.AreEqual ("value(System.Object).ToString()", call.ToString ());
143 public void CallStringIsNullOrEmpty ()
145 var call = Expression.Call (null, typeof (string).GetMethod ("IsNullOrEmpty"), Expression.Constant (""));
146 Assert.AreEqual ("IsNullOrEmpty(\"\")", call.ToString ());
150 [Category ("NotDotNet")] // http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=339351
151 [ExpectedException (typeof (ArgumentException))]
152 public void CallStaticMethodWithInstanceArgument ()
155 Expression.Parameter (GetType (), "t"),
156 GetType ().GetMethod ("Identity"),
157 Expression.Constant (null));
160 public static object Identity (object o)
166 public void CompileSimpleStaticCall ()
168 var p = Expression.Parameter (typeof (object), "o");
169 var lambda = Expression.Lambda<Func<object, object>> (Expression.Call (GetType ().GetMethod ("Identity"), p), p);
171 var i = lambda.Compile ();
173 Assert.AreEqual (2, i (2));
174 Assert.AreEqual ("Foo", i ("Foo"));
178 public void CompileSimpleInstanceCall ()
180 var p = Expression.Parameter (typeof (string), "p");
181 var lambda = Expression.Lambda<Func<string, string>> (
183 p, typeof (string).GetMethod ("ToString", Type.EmptyTypes)),
186 var ts = lambda.Compile ();
188 Assert.AreEqual ("foo", ts ("foo"));
189 Assert.AreEqual ("bar", ts ("bar"));
193 [ExpectedException (typeof (InvalidOperationException))]
194 public void CheckTypeArgsIsNotUsedForParameterLookup ()
196 Expression.Call (GetType (), "EineMethod", new [] { typeof (string), typeof (int) }, "foo".ToConstant (), 2.ToConstant ());
199 public static void EineGenericMethod<X, Y> (string foo, int bar)
204 public void CheckTypeArgsIsUsedForGenericArguments ()
206 var m = Expression.Call (GetType (), "EineGenericMethod", new [] { typeof (string), typeof (int) }, "foo".ToConstant (), 2.ToConstant ());
207 Assert.IsNotNull (m.Method);
208 Assert.AreEqual ("Void EineGenericMethod[String,Int32](System.String, Int32)", m.Method.ToString ());
211 public struct EineStrukt {
215 public EineStrukt (string foo)
220 public string GimmeFoo ()
227 [Category ("NotWorkingInterpreter")]
228 public void CallMethodOnStruct ()
230 var param = Expression.Parameter (typeof (EineStrukt), "s");
231 var foo = Expression.Lambda<Func<EineStrukt, string>> (
232 Expression.Call (param, typeof (EineStrukt).GetMethod ("GimmeFoo")), param).Compile ();
234 var s = new EineStrukt ("foo");
235 Assert.AreEqual ("foo", foo (s));
238 public static int OneStaticMethod ()
244 public void CallMethodOnDateTime ()
246 var left = Expression.Call (Expression.Constant (DateTime.Now), typeof(DateTime).GetMethod ("AddDays"), Expression.Constant (-5.0));
247 var right = Expression.Constant (DateTime.Today.AddDays (1));
248 var expr = Expression.GreaterThan (left, right);
250 var eq = Expression.Lambda<Func<bool>> (expr).Compile ();
251 Assert.IsFalse (eq ());
255 [Category ("NotDotNet")] // http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=339351
256 [ExpectedException (typeof (ArgumentException))]
257 public void CallStaticMethodOnNonSenseInstanceExpression ()
260 Expression.Constant ("la la la"),
261 this.GetType ().GetMethod ("OneStaticMethod"));
264 public static int DoSomethingWith (ref int a)
269 public static string DoAnotherThing (ref int a, string s)
275 [Category ("NotWorkingInterpreter")]
276 public void CallStaticMethodWithRefParameter ()
278 var p = Expression.Parameter (typeof (int), "i");
280 var c = Expression.Lambda<Func<int, int>> (
281 Expression.Call (GetType ().GetMethod ("DoSomethingWith"), p), p).Compile ();
283 Assert.AreEqual (42, c (38));
287 [Category ("NotWorkingInterpreter")]
288 public void CallStaticMethodWithRefParameterAndOtherParameter ()
290 var i = Expression.Parameter (typeof (int), "i");
291 var s = Expression.Parameter (typeof (string), "s");
293 var lamda = Expression.Lambda<Func<int, string, string>> (
294 Expression.Call (GetType ().GetMethod ("DoAnotherThing"), i, s), i, s).Compile ();
296 Assert.AreEqual ("foo42", lamda (42, "foo"));
300 public void CallDynamicMethod_ToString ()
302 // Regression test for #49686
303 var m = new DynamicMethod ("intIntId", typeof (int), new Type [] { typeof (int) });
304 var ilg = m.GetILGenerator ();
305 ilg.Emit (OpCodes.Ldarg_0);
306 ilg.Emit (OpCodes.Ret);
308 var i = Expression.Parameter (typeof (int), "i");
309 var e = Expression.Call (m, i);
311 Assert.IsNotNull (e.ToString ());
315 public void CallDynamicMethod_CompileInvoke ()
317 var m = new DynamicMethod ("intIntId", typeof (int), new Type [] { typeof (int) });
318 var ilg = m.GetILGenerator ();
319 ilg.Emit (OpCodes.Ldarg_0);
320 ilg.Emit (OpCodes.Ret);
322 var i = Expression.Parameter (typeof (int), "i");
323 var e = Expression.Call (m, i);
325 var lambda = Expression.Lambda<Func<int, int>> (e, i).Compile ();
326 Assert.AreEqual (42, lambda (42));
329 public static int Bang (Expression i)
331 return (int) (i as ConstantExpression).Value;
333 static bool fout_called = false;
335 public static int FooOut (out int x)
342 [Category ("NotWorkingInterpreter")]
343 public void Connect282729 ()
345 // test from https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=282729
347 var p = Expression.Parameter (typeof (int), "p");
348 var lambda = Expression.Lambda<Func<int, int>> (
350 GetType ().GetMethod ("FooOut"),
351 Expression.ArrayIndex(
352 Expression.NewArrayBounds (
358 Assert.AreEqual (0, lambda (0));
359 Assert.IsTrue (fout_called);
362 public static int FooOut2 (out int x)
369 [Category ("NotWorking")]
370 [Category ("NotWorkingInterpreter")]
371 public void Connect290278 ()
373 // test from https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=290278
375 var p = Expression.Parameter (typeof (int [,]), "p");
376 var lambda = Expression.Lambda<Func<int [,], int>> (
378 GetType ().GetMethod ("FooOut2"),
379 Expression.ArrayIndex (p, 0.ToConstant (), 0.ToConstant ())),
382 int [,] data = { { 1 } };
384 Assert.AreEqual (3, lambda (data));
385 Assert.AreEqual (2, data [0, 0]);
388 public static void FooRef (ref string s)
393 [Category ("NotWorkingInterpreter")]
394 public void Connect297597 ()
396 // test from https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=297597
398 var strings = new string [1];
400 var lambda = Expression.Lambda<Action> (
402 GetType ().GetMethod ("FooRef"),
403 Expression.ArrayIndex (
404 Expression.Constant (strings), 0.ToConstant ()))).Compile ();
410 [Category ("NotDotNet")] // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=319190
411 public void Connect319190 ()
413 var lambda = Expression.Lambda<Func<bool>> (
415 Expression.New (typeof (TypedReference)),
416 typeof (object))).Compile ();
418 Assert.IsTrue (lambda ());
421 public static int Truc ()
427 public void Connect282702 ()
429 var lambda = Expression.Lambda<Func<Func<int>>> (
432 typeof (Delegate).GetMethod ("CreateDelegate", new [] { typeof (Type), typeof (object), typeof (MethodInfo) }),
433 Expression.Constant (typeof (Func<int>), typeof (Type)),
434 Expression.Constant (null, typeof (object)),
435 Expression.Constant (GetType ().GetMethod ("Truc"))),
436 typeof (Func<int>))).Compile ();
438 Assert.AreEqual (42, lambda ().Invoke ());
442 public void CallQueryableWhere ()
444 var queryable = new [] { 1, 2, 3 }.AsQueryable ();
446 var parameter = Expression.Parameter (typeof (int), "i");
447 var lambda = Expression.Lambda<Func<int, bool>> (
448 Expression.LessThan (parameter, Expression.Constant (2)),
451 var selector = Expression.Quote (lambda);
453 var call = Expression.Call (
456 new [] { typeof (int) },
457 queryable.Expression,
460 Assert.IsNotNull (call);
461 Assert.IsNotNull (call.Method);
465 public void CallAsQueryable () // #537768
467 var constant = Expression.Constant (
469 typeof (IEnumerable<string>));
471 var call = Expression.Call (
474 new [] { typeof (string) },
477 Assert.IsNotNull (call);
478 Assert.AreEqual (1, call.Arguments.Count);
479 Assert.AreEqual (constant, call.Arguments [0]);
481 var method = call.Method;
483 Assert.AreEqual ("AsQueryable", method.Name);
484 Assert.IsTrue (method.IsGenericMethod);
485 Assert.AreEqual (typeof (string), method.GetGenericArguments () [0]);
490 public void CallQueryableSelect () // #536637
492 var parameter = Expression.Parameter (typeof (string), "s");
493 var string_length = Expression.Property (parameter, typeof (string).GetProperty ("Length"));
494 var lambda = Expression.Lambda (string_length, parameter);
496 var strings = new [] { "1", "22", "333" };
498 var call = Expression.Call (
501 new [] { typeof (string), typeof (int) },
502 Expression.Constant (strings.AsQueryable ()),
505 Assert.IsNotNull (call);
507 var method = call.Method;
509 Assert.AreEqual ("Select", method.Name);
510 Assert.IsTrue (method.IsGenericMethod);
511 Assert.AreEqual (typeof (string), method.GetGenericArguments () [0]);
512 Assert.AreEqual (typeof (int), method.GetGenericArguments () [1]);
516 [Category ("NotWorkingInterpreter")]
517 public void CallNullableGetValueOrDefault () // #568989
519 var value = Expression.Parameter (typeof (int?), "value");
520 var default_parameter = Expression.Parameter (typeof (int), "default");
522 var getter = Expression.Lambda<Func<int?, int, int>> (
529 default_parameter).Compile ();
531 Assert.AreEqual (2, getter (null, 2));
532 Assert.AreEqual (4, getter (4, 2));
536 public void CallToStringOnEnum () // #625367
538 var lambda = Expression.Lambda<Func<string>> (
540 Expression.Constant (TypeCode.Boolean, typeof (TypeCode)),
541 typeof (object).GetMethod ("ToString"))).Compile ();
543 Assert.AreEqual ("Boolean", lambda ());
546 public static void AcceptsIEnumerable(IEnumerable<object> o)
551 public void CallIQueryableMethodWithNewArrayBoundExpression () // #2304
554 GetType ().GetMethod ("AcceptsIEnumerable", BindingFlags.Public | BindingFlags.Static),
555 Expression.NewArrayBounds (typeof (object), Expression.Constant (0)));