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:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
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
20 // Miguel de Icaza (miguel@novell.com)
21 // Jb Evain (jbevain@novell.com)
25 using System
.Reflection
;
27 using System
.Linq
.Expressions
;
28 using NUnit
.Framework
;
30 namespace MonoTests
.System
.Linq
.Expressions
33 public class ExpressionTest_Lambda
36 [ExpectedException (typeof (ArgumentException
))]
37 public void NonDelegateTypeInCtor ()
39 // The first parameter must be a delegate type
40 Expression
.Lambda (typeof(string), Expression
.Constant (1), new ParameterExpression
[0]);
43 delegate object delegate_object_emtpy ();
44 delegate object delegate_object_int (int a
);
45 delegate object delegate_object_string (string s
);
46 delegate object delegate_object_object (object s
);
49 [ExpectedException (typeof (ArgumentException
))]
50 public void InvalidConversion ()
52 // float to object, invalid
53 Expression
.Lambda (typeof (delegate_object_emtpy
), Expression
.Constant (1.0), new ParameterExpression
[0]);
57 [ExpectedException (typeof (ArgumentException
))]
58 public void InvalidConversion2 ()
60 // float to object, invalid
61 Expression
.Lambda (typeof (delegate_object_emtpy
), Expression
.Constant (1), new ParameterExpression
[0]);
65 [ExpectedException (typeof (ArgumentException
))]
66 public void InvalidArgCount ()
68 // missing a parameter
69 Expression
.Lambda (typeof (delegate_object_int
), Expression
.Constant ("foo"), new ParameterExpression
[0]);
73 [ExpectedException (typeof (ArgumentException
))]
74 public void InvalidArgCount2 ()
77 ParameterExpression p
= Expression
.Parameter (typeof (int), "AAA");
78 Expression
.Lambda (typeof (delegate_object_emtpy
), Expression
.Constant ("foo"), new ParameterExpression
[1] {p}
);
82 [ExpectedException (typeof (ArgumentException
))]
83 public void InvalidArgType ()
85 // invalid argument type
86 ParameterExpression p
= Expression
.Parameter (typeof (string), "AAA");
87 Expression
.Lambda (typeof (delegate_object_int
), Expression
.Constant ("foo"), new ParameterExpression
[1] {p}
);
91 [ExpectedException (typeof (ArgumentException
))]
92 public void InvalidArgType2 ()
94 // invalid argument type
96 ParameterExpression p
= Expression
.Parameter (typeof (string), "AAA");
97 Expression
.Lambda (typeof (delegate_object_object
), Expression
.Constant ("foo"), new ParameterExpression
[1] {p}
);
101 [ExpectedException (typeof (ArgumentNullException
))]
102 public void NullParameter ()
104 Expression
.Lambda
<Func
<int, int>> (Expression
.Constant (1), new ParameterExpression
[] { null }
);
108 public void Assignability ()
110 // allowed: string to object
111 Expression
.Lambda (typeof (delegate_object_emtpy
), Expression
.Constant ("string"), new ParameterExpression
[0]);
113 // allowed delegate has string, delegate has base class (object)
114 ParameterExpression p
= Expression
.Parameter (typeof (object), "ParObject");
115 var l
= Expression
.Lambda (typeof (delegate_object_string
), Expression
.Constant (""), new ParameterExpression
[1] {p}
);
117 Assert
.AreEqual ("ParObject => \"\"", l
.ToString ());
121 [ExpectedException(typeof(InvalidOperationException
))]
122 public void ParameterOutOfScope ()
124 ParameterExpression a
= Expression
.Parameter(typeof (int), "a");
125 ParameterExpression second_a
= Expression
.Parameter(typeof(int), "a");
127 // Here we have the same name for the parameter expression, but
128 // we pass a different object to the Lambda expression, so they are
129 // different, this should throw
130 Expression
<Func
<int,int>> l
= Expression
.Lambda
<Func
<int,int>>(a
, new ParameterExpression
[] { second_a }
);
135 public void ParameterRefTest ()
137 ParameterExpression a
= Expression
.Parameter(typeof(int), "a");
138 ParameterExpression b
= Expression
.Parameter(typeof(int), "b");
140 Expression
<Func
<int,int,int>> l
= Expression
.Lambda
<Func
<int,int,int>>(
141 Expression
.Add (a
, b
), new ParameterExpression
[] { a, b }
);
143 Assert
.AreEqual (typeof (Func
<int, int, int>), l
.Type
);
144 Assert
.AreEqual ("(a, b) => (a + b)", l
.ToString ());
146 Func
<int,int,int> xx
= l
.Compile ();
147 int res
= xx (10, 20);
148 Assert
.AreEqual (res
, 30);
152 public void Compile ()
154 Expression
<Func
<int>> l
= Expression
.Lambda
<Func
<int>> (Expression
.Constant (1), new ParameterExpression
[0]);
155 Assert
.AreEqual (typeof (Func
<int>), l
.Type
);
156 Assert
.AreEqual ("() => 1", l
.ToString ());
158 Func
<int> fi
= l
.Compile ();
163 [ExpectedException(typeof(ArgumentException
))]
164 public void ReturnValueCheck ()
166 ParameterExpression p1
= Expression
.Parameter(typeof(int?), "va");
167 ParameterExpression p2
= Expression
.Parameter(typeof(int?), "vb");
168 Expression
add = Expression
.Add(p1
, p2
);
171 // This should throw, since the add.Type is "int?" and the return
172 // type we have here is int.
173 Expression
.Lambda
<Func
<int?,int?,int>> (add, p1
, p2
);
176 public static void Foo ()
181 public void LambdaType ()
183 var l
= Expression
.Lambda (Expression
.Constant (1), new [] { Expression.Parameter (typeof (int), "foo") }
);
185 Assert
.AreEqual (typeof (Func
<int, int>), l
.Type
);
187 l
= Expression
.Lambda (Expression
.Call (null, GetType ().GetMethod ("Foo")), new [] { Expression.Parameter (typeof (string), "foofoo") }
);
189 Assert
.AreEqual (typeof (Action
<string>), l
.Type
);
193 public void UnTypedLambdaReturnsExpressionOfDelegateType ()
195 var l
= Expression
.Lambda ("foo".ToConstant ());
197 Assert
.AreEqual (typeof (Expression
<Func
<string>>), l
.GetType ());
200 public static int CallDelegate (Func
<int, int> e
)
206 public void LambdaPassedAsDelegate ()
208 var pi
= Expression
.Parameter (typeof (int), "i");
209 var identity
= Expression
.Lambda
<Func
<int, int>> (pi
, pi
);
211 var l
= Expression
.Lambda
<Func
<int>> (
213 GetType ().GetMethod ("CallDelegate"),
214 identity
)).Compile ();
216 Assert
.AreEqual (42, l ());
220 [Category ("NotWorking")]
221 public void LambdaPassedAsDelegateUsingParentParameter ()
223 var a
= Expression
.Parameter (typeof (int), "a");
224 var b
= Expression
.Parameter (typeof (int), "b");
226 var l
= Expression
.Lambda
<Func
<int, int>> (
228 this.GetType ().GetMethod ("CallDelegate"),
229 Expression
.Lambda
<Func
<int, int>> (
230 Expression
.Multiply (a
, b
), b
)),
233 Assert
.AreEqual (84, l (2));
236 public static int CallFunc (Func
<int, int> e
, int i
)
242 public void NestedParentParameterUse ()
244 var a
= Expression
.Parameter (typeof (int), null);
245 var b
= Expression
.Parameter (typeof (int), null);
246 var c
= Expression
.Parameter (typeof (int), null);
247 var d
= Expression
.Parameter (typeof (int), null);
249 var l
= Expression
.Lambda
<Func
<int, int>> (
251 this.GetType ().GetMethod ("CallFunc"),
252 Expression
.Lambda
<Func
<int, int>> (
254 this.GetType ().GetMethod ("CallFunc"),
255 Expression
.Lambda
<Func
<int, int>> (
257 this.GetType ().GetMethod ("CallFunc"),
258 Expression
.Lambda
<Func
<int, int>> (
259 Expression
.Add (c
, d
),
261 Expression
.Add (b
, c
)),
263 Expression
.Add (a
, b
)),
268 Assert
.AreEqual (5, l (1));
272 public void LambdaReturningExpression ()
274 var l
= Expression
.Lambda
<Func
<Expression
>> (Expression
.Constant (42));
275 Assert
.AreEqual (ExpressionType
.Quote
, l
.Body
.NodeType
);
277 var quoter
= l
.Compile ();
281 Assert
.AreEqual (ExpressionType
.Constant
, q
.NodeType
);