Merge pull request #820 from brendanzagaeski/master
[mono.git] / mcs / class / System.Core / Test / System.Linq.Expressions / ExpressionTest_Coalesce.cs
index e3c4b9983da4813ec67c2a9786bb5f8eedf1f153..e9c43fe4da1252cebe8430e89daceac8eec918e5 100644 (file)
@@ -18,6 +18,7 @@
 //
 // Authors:
 //             Federico Di Gregorio <fog@initd.org>
+//             Jb Evain <jbevain@novell.com>
 
 using System;
 using System.Reflection;
@@ -48,7 +49,7 @@ namespace MonoTests.System.Linq.Expressions
                [ExpectedException (typeof (InvalidOperationException))]
                public void NonNullLeftParameter ()
                {
-                       // This throws because they are both doubles, which are never 
+                       // This throws because they are both doubles, which are never
                        Expression.Coalesce (Expression.Constant (1.0), Expression.Constant (2.0));
                }
 
@@ -62,19 +63,184 @@ namespace MonoTests.System.Linq.Expressions
                }
 
                [Test]
-               public void Coalesce_1 ()
+               public void IsCoalesceStringLifted ()
                {
-                       // Build the expression by hand for now:
-                       ParameterExpression pa = Expression.Parameter (typeof (int?), "a");
-                       ParameterExpression pb = Expression.Parameter (typeof (int?), "b");
-                       BinaryExpression c = Expression.Coalesce (pa, pb);
-                       
-                       Expression<Func<int?, int?, int?>> e = Expression.Lambda<Func<int?,int?,int?>>(
-                               c, new ParameterExpression [] { pa, pb });
+                       var coalesce = Expression.Coalesce (
+                               Expression.Parameter (typeof (string), "a"),
+                               Expression.Parameter (typeof (string), "b"));
 
-                       Func<int?,int?,int?> comp = e.Compile ();
+                       Assert.AreEqual ("(a ?? b)", coalesce.ToString ());
 
-                       Assert.AreEqual (10, comp (10, 20));
+                       Assert.IsFalse (coalesce.IsLifted);
+                       Assert.IsFalse (coalesce.IsLiftedToNull);
+               }
+
+               [Test]
+               public void IsCoalesceNullableIntLifted ()
+               {
+                       var coalesce = Expression.Coalesce (
+                               Expression.Parameter (typeof (int?), "a"),
+                               Expression.Parameter (typeof (int?), "b"));
+
+                       Assert.IsFalse (coalesce.IsLifted);
+                       Assert.IsFalse (coalesce.IsLiftedToNull);
+               }
+
+               [Test]
+               [Category ("NotWorkingInterpreter")]
+               public void CoalesceNullableInt ()
+               {
+                       var a = Expression.Parameter (typeof (int?), "a");
+                       var b = Expression.Parameter (typeof (int?), "b");
+                       var coalesce = Expression.Lambda<Func<int?, int?, int?>> (
+                               Expression.Coalesce (a, b), a, b).Compile ();
+
+                       Assert.AreEqual ((int?) 1, coalesce (1, 2));
+                       Assert.AreEqual ((int?) null, coalesce (null, null));
+                       Assert.AreEqual ((int?) 2, coalesce (null, 2));
+                       Assert.AreEqual ((int?) 2, coalesce (2, null));
+               }
+
+               [Test]
+               public void CoalesceString ()
+               {
+                       var a = Expression.Parameter (typeof (string), "a");
+                       var b = Expression.Parameter (typeof (string), "b");
+                       var coalesce = Expression.Lambda<Func<string, string, string>> (
+                               Expression.Coalesce (a, b), a, b).Compile ();
+
+                       Assert.AreEqual ("foo", coalesce ("foo", "bar"));
+                       Assert.AreEqual (null, coalesce (null, null));
+                       Assert.AreEqual ("bar", coalesce (null, "bar"));
+                       Assert.AreEqual ("foo", coalesce ("foo", null));
+               }
+
+               [Test]
+               [Category ("NotWorkingInterpreter")]
+               public void CoalesceNullableToNonNullable ()
+               {
+                       var a = Expression.Parameter (typeof (int?), "a");
+
+                       var node = Expression.Coalesce (a, Expression.Constant (99, typeof (int)));
+
+                       Assert.AreEqual (typeof (int), node.Type);
+                       Assert.IsFalse (node.IsLifted);
+                       Assert.IsFalse (node.IsLiftedToNull);
+
+                       var coalesce = Expression.Lambda<Func<int?, int>> (node, a).Compile ();
+
+                       Assert.AreEqual (5, coalesce (5));
+                       Assert.AreEqual (99, coalesce (null));
+               }
+
+               [Test]
+               [Category ("NotWorkingInterpreter")]
+               [Category ("NotDotNet")] // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=349822
+               public void CoalesceUserDefinedConversion ()
+               {
+                       var s = Expression.Parameter (typeof (string), "s");
+
+                       var coalesce = Expression.Lambda<Func<string, int>> (
+                               Expression.Coalesce (
+                                       s,
+                                       Expression.Constant (42),
+                                       Expression.Lambda<Func<string, int>> (
+                                               Expression.Call (typeof (int).GetMethod ("Parse", new [] { typeof (string) }), s), s)), s).Compile ();
+
+                       Assert.AreEqual (12, coalesce ("12"));
+                       Assert.AreEqual (42, coalesce (null));
+               }
+
+               struct Slot {
+                       int Value;
+
+                       public Slot (int v)
+                       {
+                               Value = v;
+                       }
+
+                       public static implicit operator int (Slot s)
+                       {
+                               return s.Value;
+                       }
+               }
+
+               [Test]
+               // #12987
+               [Category ("MobileNotWorking")]
+               [Category ("NotWorkingInterpreter")]
+               public void CoalesceNullableSlotIntoInteger ()
+               {
+                       var s = Expression.Parameter (typeof (Slot?), "s");
+
+                       var method = typeof (Slot).GetMethod ("op_Implicit");
+
+                       var coalesce = Expression.Lambda<Func<Slot?, int>> (
+                               Expression.Coalesce (
+                                       s,
+                                       Expression.Constant (-3),
+                                       Expression.Lambda (
+                                               Expression.Convert (s, typeof (int), method),
+                                               s)), s).Compile ();
+
+                       Assert.AreEqual (-3, coalesce (null));
+                       Assert.AreEqual (42, coalesce (new Slot (42)));
+               }
+
+               [Test]
+               [ExpectedException (typeof (ArgumentException))]
+               public void WrongCoalesceConversionParameterCount ()
+               {
+                       var s = Expression.Parameter (typeof (string), "s");
+                       var p = Expression.Parameter (typeof (string), "foo");
+
+                       Expression.Coalesce (
+                               s,
+                               42.ToConstant (),
+                               Expression.Lambda<Func<string, string, int>> (
+                                       Expression.Call (typeof (int).GetMethod ("Parse", new [] { typeof (string) }), s), s, p));
+
+               }
+
+               [Test]
+               [ExpectedException (typeof (InvalidOperationException))]
+               public void WrongCoalesceConversionParameterType ()
+               {
+                       var s = Expression.Parameter (typeof (string), "s");
+                       var i = Expression.Parameter (typeof (int), "i");
+
+                       Expression.Coalesce (
+                               s,
+                               42.ToConstant (),
+                               Expression.Lambda<Func<int, int>> (
+                                       i, i));
+
+               }
+
+               [Test]
+               [ExpectedException (typeof (InvalidOperationException))]
+               public void WrongCoalesceConversionReturnType ()
+               {
+                       var s = Expression.Parameter (typeof (string), "s");
+
+                       Expression.Coalesce (
+                               s,
+                               42.ToConstant (),
+                               Expression.Lambda<Func<string, string>> (
+                                       s, s));
+               }
+
+               [Test]
+               [ExpectedException (typeof (ArgumentException))]
+               public void CoalesceVoidUserDefinedConversion ()
+               {
+                       var s = Expression.Parameter (typeof (string), "s");
+
+                       Expression.Coalesce (
+                               s,
+                               42.ToConstant (),
+                               Expression.Lambda<Action<string>> (
+                                       Expression.Call (typeof (int).GetMethod ("Parse", new [] { typeof (string) }), s), s));
                }
        }
 }