2 // ExpressionTest_Convert.cs
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
.Reflection
;
32 using System
.Linq
.Expressions
;
33 using NUnit
.Framework
;
35 namespace MonoTests
.System
.Linq
.Expressions
{
38 public class ExpressionTest_Convert
{
41 [ExpectedException (typeof (ArgumentNullException
))]
42 public void NullExpression ()
44 Expression
.Convert (null, typeof (int));
48 [ExpectedException (typeof (ArgumentNullException
))]
49 public void NullType ()
51 Expression
.Convert (1.ToConstant (), null);
55 [ExpectedException (typeof (InvalidOperationException
))]
56 public void ConvertIntToString ()
58 Expression
.Convert (1.ToConstant (), typeof (string));
69 public void ConvertBackwardAssignability ()
71 var c
= Expression
.Convert (
72 Expression
.Constant (null, typeof (Bar
)), typeof (Foo
));
74 Assert
.AreEqual ("Convert(null)", c
.ToString ());
78 public void ConvertInterfaces ()
80 var p
= Expression
.Parameter (typeof (IFoo
), null);
82 var conv
= Expression
.Convert (p
, typeof (ITzap
));
83 Assert
.AreEqual (typeof (ITzap
), conv
.Type
);
85 Assert
.AreEqual ("Convert(<param>)", conv
.ToString ());
87 p
= Expression
.Parameter (typeof (ITzap
), null);
88 conv
= Expression
.Convert (p
, typeof (IFoo
));
90 Assert
.AreEqual (typeof (IFoo
), conv
.Type
);
92 Assert
.AreEqual ("Convert(<param>)", conv
.ToString ());
97 public void ConvertCheckedInt32ToInt64 ()
99 var c
= Expression
.ConvertChecked (
100 Expression
.Constant (2, typeof (int)), typeof (long));
102 Assert
.AreEqual (ExpressionType
.ConvertChecked
, c
.NodeType
);
103 Assert
.AreEqual ("ConvertChecked(2)", c
.ToString ());
107 public void ConvertCheckedFallbackToConvertForNonPrimitives ()
109 var p
= Expression
.ConvertChecked (
110 Expression
.Constant (null, typeof (object)), typeof (IFoo
));
112 Assert
.AreEqual (ExpressionType
.Convert
, p
.NodeType
);
116 [ExpectedException (typeof (InvalidOperationException
))]
117 public void ConvertBazToFoo ()
119 Expression
.Convert (Expression
.Parameter (typeof (Baz
), ""), typeof (Foo
));
122 struct EineStrukt { }
125 [ExpectedException (typeof (InvalidOperationException
))]
126 public void ConvertStructToFoo ()
128 Expression
.Convert (Expression
.Parameter (typeof (EineStrukt
), ""), typeof (Foo
));
132 [ExpectedException (typeof (InvalidOperationException
))]
133 public void ConvertInt32ToBool ()
135 Expression
.Convert (Expression
.Parameter (typeof (int), ""), typeof (bool));
139 public void ConvertIFooToFoo ()
141 var c
= Expression
.Convert (Expression
.Parameter (typeof (IFoo
), ""), typeof (Foo
));
142 Assert
.AreEqual (typeof (Foo
), c
.Type
);
143 Assert
.IsFalse (c
.IsLifted
);
144 Assert
.IsFalse (c
.IsLiftedToNull
);
145 Assert
.IsNull (c
.Method
);
149 public void BoxInt32 ()
151 var c
= Expression
.Convert (Expression
.Parameter (typeof (int), ""), typeof (object));
152 Assert
.AreEqual (typeof (object), c
.Type
);
153 Assert
.IsFalse (c
.IsLifted
);
154 Assert
.IsFalse (c
.IsLiftedToNull
);
155 Assert
.IsNull (c
.Method
);
159 public void UnBoxInt32 ()
161 var c
= Expression
.Convert (Expression
.Parameter (typeof (object), ""), typeof (int));
162 Assert
.AreEqual (typeof (int), c
.Type
);
163 Assert
.IsFalse (c
.IsLifted
);
164 Assert
.IsFalse (c
.IsLiftedToNull
);
165 Assert
.IsNull (c
.Method
);
169 public void ConvertInt32ToInt64 ()
171 var c
= Expression
.Convert (Expression
.Parameter (typeof (int), ""), typeof (long));
172 Assert
.AreEqual (typeof (long), c
.Type
);
173 Assert
.IsFalse (c
.IsLifted
);
174 Assert
.IsFalse (c
.IsLiftedToNull
);
175 Assert
.IsNull (c
.Method
);
179 public void ConvertInt64ToInt32 ()
181 var c
= Expression
.Convert (Expression
.Parameter (typeof (long), ""), typeof (int));
182 Assert
.AreEqual (typeof (int), c
.Type
);
183 Assert
.IsFalse (c
.IsLifted
);
184 Assert
.IsFalse (c
.IsLiftedToNull
);
185 Assert
.IsNull (c
.Method
);
191 public void ConvertEnumToInt32 ()
193 var c
= Expression
.Convert (Expression
.Parameter (typeof (EineEnum
), ""), typeof (int));
194 Assert
.AreEqual (typeof (int), c
.Type
);
195 Assert
.IsFalse (c
.IsLifted
);
196 Assert
.IsFalse (c
.IsLiftedToNull
);
197 Assert
.IsNull (c
.Method
);
201 public void ConvertNullableInt32ToInt32 ()
203 var c
= Expression
.Convert (Expression
.Parameter (typeof (int?), ""), typeof (int));
204 Assert
.AreEqual (typeof (int), c
.Type
);
205 Assert
.IsTrue (c
.IsLifted
);
206 Assert
.IsFalse (c
.IsLiftedToNull
);
207 Assert
.IsNull (c
.Method
);
211 public void ConvertInt32ToNullableInt32 ()
213 var c
= Expression
.Convert (Expression
.Parameter (typeof (int), ""), typeof (int?));
214 Assert
.AreEqual (typeof (int?), c
.Type
);
215 Assert
.IsTrue (c
.IsLifted
);
216 Assert
.IsTrue (c
.IsLiftedToNull
);
217 Assert
.IsNull (c
.Method
);
229 public static explicit operator int (Klang k
)
236 public void ConvertClassWithExplicitOp ()
238 var c
= Expression
.Convert (Expression
.Parameter (typeof (Klang
), ""), typeof (int));
239 Assert
.AreEqual (typeof (int), c
.Type
);
240 Assert
.IsFalse (c
.IsLifted
);
241 Assert
.IsFalse (c
.IsLiftedToNull
);
242 Assert
.IsNotNull (c
.Method
);
246 public void CompileConvertClassWithExplicitOp ()
248 var p
= Expression
.Parameter (typeof (Klang
), "klang");
249 var c
= Expression
.Lambda
<Func
<Klang
, int>> (
250 Expression
.Convert (p
, typeof (int)), p
).Compile ();
252 Assert
.AreEqual (42, c (new Klang (42)));
256 public void ConvertClassWithExplicitOpToNullableInt ()
258 var c
= Expression
.Convert (Expression
.Parameter (typeof (Klang
), ""), typeof (int?));
259 Assert
.AreEqual (typeof (int?), c
.Type
);
260 Assert
.IsTrue (c
.IsLifted
);
261 Assert
.IsTrue (c
.IsLiftedToNull
);
262 Assert
.IsNotNull (c
.Method
);
273 public static implicit operator int (Kling k
)
280 public void ConvertStructWithImplicitOp ()
282 var c
= Expression
.Convert (Expression
.Parameter (typeof (Kling
), ""), typeof (int));
283 Assert
.AreEqual (typeof (int), c
.Type
);
284 Assert
.IsFalse (c
.IsLifted
);
285 Assert
.IsFalse (c
.IsLiftedToNull
);
286 Assert
.IsNotNull (c
.Method
);
290 public void CompileConvertStructWithImplicitOp ()
292 var p
= Expression
.Parameter (typeof (Kling
), "kling");
293 var c
= Expression
.Lambda
<Func
<Kling
, int>> (
294 Expression
.Convert (p
, typeof (int)), p
).Compile ();
296 Assert
.AreEqual (42, c (new Kling (42)));
300 public void ConvertStructWithImplicitOpToNullableInt ()
302 var c
= Expression
.Convert (Expression
.Parameter (typeof (Kling
), ""), typeof (int?));
303 Assert
.AreEqual (typeof (int?), c
.Type
);
304 Assert
.IsTrue (c
.IsLifted
);
305 Assert
.IsTrue (c
.IsLiftedToNull
);
306 Assert
.IsNotNull (c
.Method
);
310 public void ConvertNullableStructWithImplicitOpToNullableInt ()
312 var c
= Expression
.Convert (Expression
.Parameter (typeof (Kling
?), ""), typeof (int?));
313 Assert
.AreEqual (typeof (int?), c
.Type
);
314 Assert
.IsTrue (c
.IsLifted
);
315 Assert
.IsTrue (c
.IsLiftedToNull
);
316 Assert
.IsNotNull (c
.Method
);
320 public void CompiledBoxing ()
322 var b
= Expression
.Lambda
<Func
<object>> (
323 Expression
.Convert (42.ToConstant (), typeof (object))).Compile ();
325 Assert
.AreEqual ((object) 42, b ());
329 public void CompiledUnBoxing ()
331 var p
= Expression
.Parameter (typeof (object), "o");
333 var u
= Expression
.Lambda
<Func
<object, int>> (
334 Expression
.Convert (p
, typeof (int)), p
).Compile ();
336 Assert
.AreEqual (42, u ((object) 42));
340 public void CompiledCast ()
342 var p
= Expression
.Parameter (typeof (IFoo
), "foo");
344 var c
= Expression
.Lambda
<Func
<IFoo
, Bar
>> (
345 Expression
.Convert (p
, typeof (Bar
)), p
).Compile ();
347 IFoo foo
= new Bar ();
351 Assert
.AreEqual (b
, foo
);
355 public void CompileNotNullableToNullable ()
357 var p
= Expression
.Parameter (typeof (int), "i");
358 var c
= Expression
.Lambda
<Func
<int, int?>> (
359 Expression
.Convert (p
, typeof (int?)), p
).Compile ();
361 Assert
.AreEqual ((int?) 0, c (0));
362 Assert
.AreEqual ((int?) 42, c (42));
366 public void CompileNullableToNotNullable ()
368 var p
= Expression
.Parameter (typeof (int?), "i");
369 var c
= Expression
.Lambda
<Func
<int?, int>> (
370 Expression
.Convert (p
, typeof (int)), p
).Compile ();
372 Assert
.AreEqual (0, c ((int?) 0));
373 Assert
.AreEqual (42, c ((int?) 42));
375 Action a
= () => c (null);
377 a
.AssertThrows (typeof (InvalidOperationException
));
381 public void CompiledConvertToSameType ()
383 var k
= new Klang (42);
385 var p
= Expression
.Parameter (typeof (Klang
), "klang");
386 var c
= Expression
.Lambda
<Func
<Klang
, Klang
>> (
391 Assert
.AreEqual (k
, c (k
));
395 public void CompiledConvertNullableToNullable ()
397 var p
= Expression
.Parameter (typeof (int?), "i");
398 var c
= Expression
.Lambda
<Func
<int?, short?>> (
399 Expression
.Convert (p
, typeof (short?)), p
).Compile ();
401 Assert
.AreEqual ((short?) null, c (null));
402 Assert
.AreEqual ((short?) 12, c (12));
406 public void CompiledNullableBoxing ()
408 var p
= Expression
.Parameter (typeof (int?), "i");
409 var c
= Expression
.Lambda
<Func
<int?, object>> (
410 Expression
.Convert (p
, typeof (object)), p
).Compile ();
412 Assert
.AreEqual (null, c (null));
413 Assert
.AreEqual ((object) (int?) 42, c (42));
417 public void CompiledNullableUnboxing ()
419 var p
= Expression
.Parameter (typeof (object), "o");
420 var c
= Expression
.Lambda
<Func
<object, int?>> (
421 Expression
.Convert (p
, typeof (int?)), p
).Compile ();
423 Assert
.AreEqual ((int?) null, c (null));
424 Assert
.AreEqual ((int?) 42, c ((int?) 42));
428 public void ChainedNullableConvert ()
430 var p
= Expression
.Parameter (typeof (sbyte?), "a");
432 var test
= Expression
.Lambda
<Func
<sbyte?, long?>> (
437 typeof (long?)), p
).Compile ();
439 Assert
.AreEqual ((long?) 3, test ((sbyte?) 3));
440 Assert
.AreEqual (null, test (null));
443 struct ImplicitToShort
{
446 public ImplicitToShort (short v
)
451 public static implicit operator short (ImplicitToShort i
)
458 public void ConvertImplicitToShortToNullableInt ()
460 var a
= Expression
.Parameter (typeof (ImplicitToShort
?), "a");
462 var method
= typeof (ImplicitToShort
).GetMethod ("op_Implicit");
464 var node
= Expression
.Convert (a
, typeof (short), method
);
465 Assert
.IsTrue (node
.IsLifted
);
466 Assert
.IsFalse (node
.IsLiftedToNull
);
467 Assert
.AreEqual (typeof (short), node
.Type
);
468 Assert
.AreEqual (method
, node
.Method
);
470 var conv
= Expression
.Lambda
<Func
<ImplicitToShort
?, int?>> (
473 typeof (int?)), a
).Compile ();
475 Assert
.AreEqual ((int?) 42, conv (new ImplicitToShort (42)));
477 Action convnull
= () => Assert
.AreEqual (null, conv (null));
479 convnull
.AssertThrows (typeof (InvalidOperationException
));
483 public void NullableImplicitToShort ()
485 var i
= Expression
.Parameter (typeof (ImplicitToShort
?), "i");
487 var method
= typeof (ImplicitToShort
).GetMethod ("op_Implicit");
489 var node
= Expression
.Convert (i
, typeof (short?), method
);
491 Assert
.IsTrue (node
.IsLifted
);
492 Assert
.IsTrue (node
.IsLiftedToNull
);
493 Assert
.AreEqual (typeof (short?), node
.Type
);
494 Assert
.AreEqual (method
, node
.Method
);
496 var convert
= Expression
.Lambda
<Func
<ImplicitToShort
?, short?>> (node
, i
).Compile ();
498 Assert
.AreEqual ((short?) 42, convert (new ImplicitToShort (42)));
502 public void ConvertLongToDecimal ()
504 var p
= Expression
.Parameter (typeof (long), "l");
506 var node
= Expression
.Convert (p
, typeof (decimal));
507 Assert
.IsFalse (node
.IsLifted
);
508 Assert
.IsFalse (node
.IsLiftedToNull
);
509 Assert
.AreEqual (typeof (decimal), node
.Type
);
510 Assert
.IsNotNull (node
.Method
);
512 var convert
= Expression
.Lambda
<Func
<long, decimal>> (node
, p
).Compile ();
514 Assert
.AreEqual (42, convert (42));
518 public void ConvertNullableULongToNullableDecimal ()
520 var p
= Expression
.Parameter (typeof (ulong?), "l");
522 var node
= Expression
.Convert (p
, typeof (decimal?));
523 Assert
.IsTrue (node
.IsLifted
);
524 Assert
.IsTrue (node
.IsLiftedToNull
);
525 Assert
.AreEqual (typeof (decimal?), node
.Type
);
526 Assert
.IsNotNull (node
.Method
);
528 var convert
= Expression
.Lambda
<Func
<ulong?, decimal?>> (node
, p
).Compile ();
530 Assert
.AreEqual (42, convert (42));
531 Assert
.AreEqual (null, convert (null));
535 public void ConvertCheckedNullableIntToInt ()
537 var p
= Expression
.Parameter (typeof (int?), "i");
539 var node
= Expression
.ConvertChecked (p
, typeof (int));
540 Assert
.AreEqual (ExpressionType
.ConvertChecked
, node
.NodeType
);
541 Assert
.IsTrue (node
.IsLifted
);
542 Assert
.IsFalse (node
.IsLiftedToNull
);
543 Assert
.AreEqual (typeof (int), node
.Type
);
544 Assert
.IsNull (node
.Method
);
547 struct ImplicitToInt
{
550 public ImplicitToInt (int v
)
555 public static implicit operator int (ImplicitToInt i
)
562 public void ConvertNullableImplictToIntToNullableLong ()
564 var i
= Expression
.Parameter (typeof (ImplicitToInt
?), "i");
566 var method
= typeof (ImplicitToInt
).GetMethod ("op_Implicit");
568 var node
= Expression
.Convert (i
, typeof (int), method
);
569 node
= Expression
.Convert (node
, typeof (long?));
570 var conv
= Expression
.Lambda
<Func
<ImplicitToInt
?, long?>> (node
, i
).Compile ();
572 Assert
.AreEqual ((long?) 42, conv (new ImplicitToInt (42)));
573 Action convnull
= () => Assert
.AreEqual (null, conv (null));
574 convnull
.AssertThrows (typeof (InvalidOperationException
));
578 [ExpectedException (typeof (InvalidOperationException
))]
579 [Category ("NotWorking")]
580 public void ConvertNullableIntToStringWithConvertMethod ()
583 Expression
.Constant ((int?) 0),
585 typeof (Convert
).GetMethod ("ToString", new [] { typeof (object) }
));