5 // Jb Evain (jbevain@novell.com)
7 // (C) 2008 Novell, Inc. (http://www.novell.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System
.Collections
.Generic
;
31 using System
.Reflection
;
32 using System
.Runtime
.CompilerServices
;
34 using System
.Linq
.Expressions
;
36 using NUnit
.Framework
;
38 namespace MonoTests
.System
.Linq
.Expressions
{
41 public class ExpressionTest
{
44 [ExpectedException (typeof (ArgumentNullException
))]
45 public void GetFuncTypeArgNull ()
47 Expression
.GetFuncType (null);
50 static Type
[] GetTestTypeArray (int length
)
52 return Enumerable
.Range (0, length
- 1)
53 .Select (i
=> typeof (int))
58 [ExpectedException (typeof (ArgumentException
))]
59 public void GetFuncTypeArgEmpty ()
61 Expression
.GetFuncType (Type
.EmptyTypes
);
65 [ExpectedException (typeof (ArgumentException
))]
66 public void GetFuncTypeArgTooBig ()
68 Expression
.GetFuncType (GetTestTypeArray (64));
72 public void GetFuncTypeTest ()
74 var func
= Expression
.GetFuncType (new [] {typeof (int)}
);
75 Assert
.AreEqual (typeof (Func
<int>), func
);
77 func
= Expression
.GetFuncType (new [] {typeof (int), typeof (int)}
);
78 Assert
.AreEqual (typeof (Func
<int, int>), func
);
80 func
= Expression
.GetFuncType (new [] {typeof (int), typeof (int), typeof (int)}
);
81 Assert
.AreEqual (typeof (Func
<int, int, int>), func
);
83 func
= Expression
.GetFuncType (new [] {typeof (int), typeof (int), typeof (int), typeof (int)}
);
84 Assert
.AreEqual (typeof (Func
<int, int, int, int>), func
);
86 func
= Expression
.GetFuncType (new [] {typeof (int), typeof (int), typeof (int), typeof (int), typeof (int)}
);
87 Assert
.AreEqual (typeof (Func
<int, int, int, int, int>), func
);
91 [ExpectedException (typeof (ArgumentNullException
))]
92 public void GetActionTypeArgNull ()
94 Expression
.GetActionType (null);
98 [ExpectedException (typeof (ArgumentException
))]
99 public void GetActionTypeArgTooBig ()
101 Expression
.GetActionType (GetTestTypeArray (45));
105 public void GetActionTypeTest ()
107 var action
= Expression
.GetActionType (new Type
[0]);
108 Assert
.AreEqual (typeof (Action
), action
);
110 action
= Expression
.GetActionType (new [] {typeof (int)}
);
111 Assert
.AreEqual (typeof (Action
<int>), action
);
113 action
= Expression
.GetActionType (new [] {typeof (int), typeof (int)}
);
114 Assert
.AreEqual (typeof (Action
<int, int>), action
);
116 action
= Expression
.GetActionType (new [] {typeof (int), typeof (int), typeof (int)}
);
117 Assert
.AreEqual (typeof (Action
<int, int, int>), action
);
119 action
= Expression
.GetActionType (new [] {typeof (int), typeof (int), typeof (int), typeof (int)}
);
120 Assert
.AreEqual (typeof (Action
<int, int, int, int>), action
);
124 [ExpectedException (typeof (ArgumentNullException
))]
125 public void ParameterNullType ()
127 Expression
.Parameter (null, "foo");
131 public void ParameterNullName ()
133 var p
= Expression
.Parameter (typeof (string), null);
134 Assert
.AreEqual (null, p
.Name
);
135 Assert
.AreEqual (typeof (string), p
.Type
);
137 Assert
.AreEqual ("<param>", p
.ToString ());
142 public void ParameterEmptyName ()
144 var p
= Expression
.Parameter (typeof (string), "");
145 Assert
.AreEqual ("", p
.Name
);
146 Assert
.AreEqual (typeof (string), p
.Type
);
148 Assert
.AreEqual ("", p
.ToString ());
153 public void Parameter ()
155 var p
= Expression
.Parameter (typeof (string), "foo");
156 Assert
.AreEqual ("foo", p
.Name
);
157 Assert
.AreEqual (typeof (string), p
.Type
);
158 Assert
.AreEqual ("foo", p
.ToString ());
162 [Category ("NotDotNet")]
163 [ExpectedException (typeof (ArgumentException
))]
164 public void VoidParameter ()
166 Expression
.Parameter (typeof (void), "hello");
171 public static int Identity (int i
)
178 public void CompileActionDiscardingRetValue ()
180 var p
= Expression
.Parameter (typeof (int), "i");
181 var identity
= GetType ().GetMethod ("Identity", BindingFlags
.Static
| BindingFlags
.Public
);
182 Assert
.IsNotNull (identity
);
184 var lambda
= Expression
.Lambda
<Action
<int>> (Expression
.Call (identity
, p
), p
);
186 var method
= lambda
.Compile ();
191 Assert
.AreEqual (42, buffer
);
195 [Category("TargetJvmNotSupported")]
196 public void ExpressionDelegateTarget ()
198 var p
= Expression
.Parameter (typeof (string), "str");
199 var identity
= Expression
.Lambda
<Func
<string, string>> (p
, p
).Compile ();
201 Assert
.AreEqual (typeof (Func
<string, string>), identity
.GetType ());
202 Assert
.IsNotNull (identity
.Target
);
204 Assert
.AreEqual (typeof (ExecutionScope
), identity
.Target
.GetType ());
209 public string gazonk
;
215 public override string ToString ()
217 return baz
.ToString ();
223 [Category ("TargetJvmNotSupported")]
224 public void GlobalsInScope ()
226 var foo
= new Foo { gazonk = "gazonk" }
;
227 var bar
= new Bar { baz = 42 }
;
229 var l
= Expression
.Lambda
<Func
<string>> (
231 typeof (string).GetMethod ("Concat", new [] { typeof (string), typeof (string) }
),
232 Expression
.Field (Expression
.Constant (foo
), typeof (Foo
).GetField ("gazonk")),
233 Expression
.Call (Expression
.Constant (bar
), typeof (Bar
).GetMethod ("ToString"))));
235 var del
= l
.Compile ();
237 var scope
= del
.Target
as ExecutionScope
;
239 Assert
.IsNotNull (scope
);
241 var globals
= scope
.Globals
;
243 Assert
.IsNotNull (globals
);
245 Assert
.AreEqual (2, globals
.Length
);
246 Assert
.AreEqual (typeof (StrongBox
<Foo
>), globals
[0].GetType ());
247 Assert
.AreEqual (typeof (StrongBox
<Bar
>), globals
[1].GetType ());
249 Assert
.AreEqual (foo
, ((StrongBox
<Foo
>) globals
[0]).Value
);
250 Assert
.AreEqual (bar
, ((StrongBox
<Bar
>) globals
[1]).Value
);
252 Assert
.AreEqual ("gazonk42", del ());
257 public void SimpleHoistedParameter ()
259 var p
= Expression
.Parameter (typeof (string), "s");
261 var f
= Expression
.Lambda
<Func
<string, Func
<string>>> (
262 Expression
.Lambda
<Func
<string>> (
264 new ParameterExpression
[0]),
269 Assert
.AreEqual ("x", f2 ());
273 public void TwoHoistingLevels ()
275 var p1
= Expression
.Parameter (typeof (string), "x");
276 var p2
= Expression
.Parameter (typeof (string), "y");
278 Expression
<Func
<string, Func
<string, Func
<string>>>> e
=
279 Expression
.Lambda
<Func
<string, Func
<string, Func
<string>>>> (
280 Expression
.Lambda
<Func
<string, Func
<string>>> (
281 Expression
.Lambda
<Func
<string>> (
283 typeof (string).GetMethod ("Concat", new [] { typeof (string), typeof (string) }
),
285 new ParameterExpression
[0]),
289 var f
= e
.Compile ();
290 var f2
= f ("Hello ");
291 var f3
= f2 ("World !");
293 Assert
.AreEqual ("Hello World !", f3 ());
297 public void HoistedParameter ()
299 var i
= Expression
.Parameter (typeof (int), "i");
301 var l
= Expression
.Lambda
<Func
<int, string>> (
303 Expression
.Lambda
<Func
<string>> (
304 Expression
.Call (i
, typeof (int).GetMethod ("ToString", Type
.EmptyTypes
)))), i
).Compile ();
306 Assert
.AreEqual ("42", l (42));