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
.Collections
.Generic
;
34 using System
.Linq
.Expressions
;
35 using NUnit
.Framework
;
37 namespace MonoTests
.System
.Linq
.Expressions
{
40 public class ExpressionTest_Call
{
43 [ExpectedException (typeof (ArgumentNullException
))]
44 public void Arg1Null ()
46 Expression
.Call ((Type
)null, "TestMethod", null, Expression
.Constant (1));
50 [ExpectedException (typeof (ArgumentNullException
))]
51 public void Arg2Null ()
53 Expression
.Call (typeof (MemberClass
), null, null, Expression
.Constant (1));
57 [ExpectedException (typeof (InvalidOperationException
))]
58 public void Arg4WrongType ()
60 Expression
.Call (typeof (MemberClass
), "StaticMethod", null, Expression
.Constant (true));
64 [ExpectedException (typeof (InvalidOperationException
))]
65 public void InstanceMethod ()
67 Expression
.Call (typeof (MemberClass
), "TestMethod", null, Expression
.Constant (1));
71 public void StaticMethod ()
73 Expression
.Call (typeof (MemberClass
), "StaticMethod", null, Expression
.Constant (1));
77 public void StaticGenericMethod ()
79 Expression
.Call (typeof (MemberClass
), "StaticGenericMethod", new [] { typeof (int) }
, Expression
.Constant (1));
83 [ExpectedException (typeof (ArgumentNullException
))]
84 public void ArgMethodNull ()
86 Expression
.Call (Expression
.Constant (new object ()), null);
90 [ExpectedException (typeof (ArgumentNullException
))]
91 public void ArgInstanceNullForNonStaticMethod ()
93 Expression
.Call (null, typeof (object).GetMethod ("ToString"));
97 [ExpectedException (typeof (ArgumentException
))]
98 public void InstanceTypeDoesntMatchMethodDeclaringType ()
100 Expression
.Call (Expression
.Constant (1), typeof (string).GetMethod ("Intern"));
104 [ExpectedException (typeof (ArgumentException
))]
105 public void MethodArgumentCountDoesnMatchParameterLength ()
107 Expression
.Call (Expression
.Constant (new object ()), typeof (object).GetMethod ("ToString"), Expression
.Constant (new object ()));
111 public void Bar (string s
)
117 [ExpectedException (typeof (ArgumentNullException
))]
118 public void MethodHasNullArgument ()
120 Expression
.Call (Expression
.New (typeof (Foo
)), typeof (Foo
).GetMethod ("Bar"), null as Expression
);
124 [ExpectedException (typeof (ArgumentException
))]
125 public void MethodArgumentDoesntMatchParameterType ()
127 Expression
.Call (Expression
.New (typeof (Foo
)), typeof (Foo
).GetMethod ("Bar"), Expression
.Constant (42));
131 public void CallToString ()
133 var call
= Expression
.Call (Expression
.Constant (new object ()), typeof (object).GetMethod ("ToString"));
134 Assert
.AreEqual ("value(System.Object).ToString()", call
.ToString ());
138 public void CallStringIsNullOrEmpty ()
140 var call
= Expression
.Call (null, typeof (string).GetMethod ("IsNullOrEmpty"), Expression
.Constant (""));
141 Assert
.AreEqual ("IsNullOrEmpty(\"\")", call
.ToString ());
145 [Category ("NotDotNet")] // http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=339351
146 [ExpectedException (typeof (ArgumentException
))]
147 public void CallStaticMethodWithInstanceArgument ()
150 Expression
.Parameter (GetType (), "t"),
151 GetType ().GetMethod ("Identity"),
152 Expression
.Constant (null));
155 public static object Identity (object o
)
161 public void CompileSimpleStaticCall ()
163 var p
= Expression
.Parameter (typeof (object), "o");
164 var lambda
= Expression
.Lambda
<Func
<object, object>> (Expression
.Call (GetType ().GetMethod ("Identity"), p
), p
);
166 var i
= lambda
.Compile ();
168 Assert
.AreEqual (2, i (2));
169 Assert
.AreEqual ("Foo", i ("Foo"));
173 public void CompileSimpleInstanceCall ()
175 var p
= Expression
.Parameter (typeof (string), "p");
176 var lambda
= Expression
.Lambda
<Func
<string, string>> (
178 p
, typeof (string).GetMethod ("ToString", Type
.EmptyTypes
)),
181 var ts
= lambda
.Compile ();
183 Assert
.AreEqual ("foo", ts ("foo"));
184 Assert
.AreEqual ("bar", ts ("bar"));
188 [ExpectedException (typeof (InvalidOperationException
))]
189 public void CheckTypeArgsIsNotUsedForParameterLookup ()
191 Expression
.Call (GetType (), "EineMethod", new [] { typeof (string), typeof (int) }
, "foo".ToConstant (), 2.ToConstant ());
194 public static void EineGenericMethod
<X
, Y
> (string foo
, int bar
)
199 public void CheckTypeArgsIsUsedForGenericArguments ()
201 var m
= Expression
.Call (GetType (), "EineGenericMethod", new [] { typeof (string), typeof (int) }
, "foo".ToConstant (), 2.ToConstant ());
202 Assert
.IsNotNull (m
.Method
);
203 Assert
.AreEqual ("Void EineGenericMethod[String,Int32](System.String, Int32)", m
.Method
.ToString ());
206 public struct EineStrukt
{
210 public EineStrukt (string foo
)
215 public string GimmeFoo ()
222 public void CallMethodOnStruct ()
224 var param
= Expression
.Parameter (typeof (EineStrukt
), "s");
225 var foo
= Expression
.Lambda
<Func
<EineStrukt
, string>> (
226 Expression
.Call (param
, typeof (EineStrukt
).GetMethod ("GimmeFoo")), param
).Compile ();
228 var s
= new EineStrukt ("foo");
229 Assert
.AreEqual ("foo", foo (s
));
232 public static int OneStaticMethod ()
238 [Category ("NotDotNet")] // http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=339351
239 [ExpectedException (typeof (ArgumentException
))]
240 public void CallStaticMethodOnNonSenseInstanceExpression ()
243 Expression
.Constant ("la la la"),
244 this.GetType ().GetMethod ("OneStaticMethod"));
247 public static int DoSomethingWith (ref int a
)
252 public static string DoAnotherThing (ref int a
, string s
)
258 public void CallStaticMethodWithRefParameter ()
260 var p
= Expression
.Parameter (typeof (int), "i");
262 var c
= Expression
.Lambda
<Func
<int, int>> (
263 Expression
.Call (GetType ().GetMethod ("DoSomethingWith"), p
), p
).Compile ();
265 Assert
.AreEqual (42, c (38));
269 public void CallStaticMethodWithRefParameterAndOtherParameter ()
271 var i
= Expression
.Parameter (typeof (int), "i");
272 var s
= Expression
.Parameter (typeof (string), "s");
274 var lamda
= Expression
.Lambda
<Func
<int, string, string>> (
275 Expression
.Call (GetType ().GetMethod ("DoAnotherThing"), i
, s
), i
, s
).Compile ();
277 Assert
.AreEqual ("foo42", lamda (42, "foo"));
280 public static int Bang (Expression i
)
282 return (int) (i
as ConstantExpression
).Value
;
286 public void CallMethodWithExpressionParameter ()
288 var call
= Expression
.Call (GetType ().GetMethod ("Bang"), Expression
.Constant (42));
289 Assert
.AreEqual (ExpressionType
.Quote
, call
.Arguments
[0].NodeType
);
291 var l
= Expression
.Lambda
<Func
<int>> (call
).Compile ();
293 Assert
.AreEqual (42, l ());
296 static bool fout_called
= false;
298 public static int FooOut (out int x
)
305 public void Connect282729 ()
307 // test from https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=282729
309 var p
= Expression
.Parameter (typeof (int), "p");
310 var lambda
= Expression
.Lambda
<Func
<int, int>> (
312 GetType ().GetMethod ("FooOut"),
313 Expression
.ArrayIndex(
314 Expression
.NewArrayBounds (
320 Assert
.AreEqual (0, lambda (0));
321 Assert
.IsTrue (fout_called
);
324 public static int FooOut2 (out int x
)
331 [Category ("NotWorking")]
332 public void Connect290278 ()
334 // test from https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=290278
336 var p
= Expression
.Parameter (typeof (int [,]), "p");
337 var lambda
= Expression
.Lambda
<Func
<int [,], int>> (
339 GetType ().GetMethod ("FooOut2"),
340 Expression
.ArrayIndex (p
, 0.ToConstant (), 0.ToConstant ())),
343 int [,] data
= { { 1 }
};
345 Assert
.AreEqual (3, lambda (data
));
346 Assert
.AreEqual (2, data
[0, 0]);
349 public static void FooRef (ref string s
)
354 public void Connect297597 ()
356 // test from https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=297597
358 var strings
= new string [1];
360 var lambda
= Expression
.Lambda
<Action
> (
362 GetType ().GetMethod ("FooRef"),
363 Expression
.ArrayIndex (
364 Expression
.Constant (strings
), 0.ToConstant ()))).Compile ();
370 [Category ("NotDotNet")] // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=319190
371 public void Connect319190 ()
373 var lambda
= Expression
.Lambda
<Func
<bool>> (
375 Expression
.New (typeof (TypedReference
)),
376 typeof (object))).Compile ();
378 Assert
.IsTrue (lambda ());
381 public static int Truc ()
387 public void Connect282702 ()
389 var lambda
= Expression
.Lambda
<Func
<Func
<int>>> (
392 typeof (Delegate
).GetMethod ("CreateDelegate", new [] { typeof (Type), typeof (object), typeof (MethodInfo) }
),
393 Expression
.Constant (typeof (Func
<int>), typeof (Type
)),
394 Expression
.Constant (null, typeof (object)),
395 Expression
.Constant (GetType ().GetMethod ("Truc"))),
396 typeof (Func
<int>))).Compile ();
398 Assert
.AreEqual (42, lambda ().Invoke ());
402 public void CallQueryableWhere ()
404 var queryable
= new [] { 1, 2, 3 }
.AsQueryable ();
406 var parameter
= Expression
.Parameter (typeof (int), "i");
407 var lambda
= Expression
.Lambda
<Func
<int, bool>> (
408 Expression
.LessThan (parameter
, Expression
.Constant (2)),
411 var selector
= Expression
.Quote (lambda
);
413 var call
= Expression
.Call (
416 new [] { typeof (int) }
,
417 queryable
.Expression
,
420 Assert
.IsNotNull (call
);
421 Assert
.IsNotNull (call
.Method
);
425 [Category ("NotWorking")]
426 public void CallAsQueryable () // #537768
428 var constant
= Expression
.Constant (
430 typeof (IEnumerable
<string>));
432 var call
= Expression
.Call (
435 new [] { typeof (string) }
,
438 Assert
.IsNotNull (call
);
439 Assert
.AreEqual (1, call
.Arguments
.Count
);
440 Assert
.AreEqual (constant
, call
.Arguments
[0]);
442 var method
= call
.Method
;
444 Assert
.AreEqual ("AsQueryable", method
.Name
);
445 Assert
.IsTrue (method
.IsGenericMethod
);
446 Assert
.AreEqual (typeof (string), method
.GetGenericArguments () [0]);
451 [Category ("NotWorking")]
452 public void CallQueryableSelect () // #536637
454 var parameter
= Expression
.Parameter (typeof (string), "s");
455 var string_length
= Expression
.Property (parameter
, typeof (string).GetProperty ("Length"));
456 var lambda
= Expression
.Lambda (string_length
, parameter
);
458 var strings
= new [] { "1", "22", "333" }
;
460 var call
= Expression
.Call (
463 new [] { typeof (string), typeof (int) }
,
464 Expression
.Constant (strings
.AsQueryable ()),
467 Assert
.IsNotNull (call
);
469 var method
= call
.Method
;
471 Assert
.AreEqual ("Select", method
.Name
);
472 Assert
.IsTrue (method
.IsGenericMethod
);
473 Assert
.AreEqual (typeof (string), method
.GetGenericArguments () [0]);
474 Assert
.AreEqual (typeof (int), method
.GetGenericArguments () [1]);