Merge branch 'BigIntegerParse'
[mono.git] / mcs / class / System.Core / Test / System.Linq.Expressions / ExpressionTest_Coalesce.cs
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:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
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
18 //
19 // Authors:
20 //              Federico Di Gregorio <fog@initd.org>
21 //              Jb Evain <jbevain@novell.com>
22
23 using System;
24 using System.Reflection;
25 using System.Linq;
26 using System.Linq.Expressions;
27 using NUnit.Framework;
28
29 namespace MonoTests.System.Linq.Expressions
30 {
31         [TestFixture]
32         public class ExpressionTest_Coalesce
33         {
34                 [Test]
35                 [ExpectedException (typeof (ArgumentNullException))]
36                 public void Arg1Null ()
37                 {
38                         Expression.Coalesce (null, Expression.Constant (1));
39                 }
40
41                 [Test]
42                 [ExpectedException (typeof (ArgumentNullException))]
43                 public void Arg2Null ()
44                 {
45                         Expression.Coalesce (Expression.Constant (1), null);
46                 }
47
48                 [Test]
49                 [ExpectedException (typeof (InvalidOperationException))]
50                 public void NonNullLeftParameter ()
51                 {
52                         // This throws because they are both doubles, which are never
53                         Expression.Coalesce (Expression.Constant (1.0), Expression.Constant (2.0));
54                 }
55
56                 [Test]
57                 [ExpectedException (typeof (ArgumentException))]
58                 public void Incompatible_Arguments ()
59                 {
60                         // The artuments are not compatible
61                         Expression.Coalesce (Expression.Parameter (typeof (int?), "a"),
62                                              Expression.Parameter (typeof (bool), "b"));
63                 }
64
65                 [Test]
66                 public void IsCoalesceStringLifted ()
67                 {
68                         var coalesce = Expression.Coalesce (
69                                 Expression.Parameter (typeof (string), "a"),
70                                 Expression.Parameter (typeof (string), "b"));
71
72                         Assert.AreEqual ("(a ?? b)", coalesce.ToString ());
73
74                         Assert.IsFalse (coalesce.IsLifted);
75                         Assert.IsFalse (coalesce.IsLiftedToNull);
76                 }
77
78                 [Test]
79                 public void IsCoalesceNullableIntLifted ()
80                 {
81                         var coalesce = Expression.Coalesce (
82                                 Expression.Parameter (typeof (int?), "a"),
83                                 Expression.Parameter (typeof (int?), "b"));
84
85                         Assert.IsFalse (coalesce.IsLifted);
86                         Assert.IsFalse (coalesce.IsLiftedToNull);
87                 }
88
89                 [Test]
90                 [Category ("NotWorkingInterpreter")]
91                 public void CoalesceNullableInt ()
92                 {
93                         var a = Expression.Parameter (typeof (int?), "a");
94                         var b = Expression.Parameter (typeof (int?), "b");
95                         var coalesce = Expression.Lambda<Func<int?, int?, int?>> (
96                                 Expression.Coalesce (a, b), a, b).Compile ();
97
98                         Assert.AreEqual ((int?) 1, coalesce (1, 2));
99                         Assert.AreEqual ((int?) null, coalesce (null, null));
100                         Assert.AreEqual ((int?) 2, coalesce (null, 2));
101                         Assert.AreEqual ((int?) 2, coalesce (2, null));
102                 }
103
104                 [Test]
105                 public void CoalesceString ()
106                 {
107                         var a = Expression.Parameter (typeof (string), "a");
108                         var b = Expression.Parameter (typeof (string), "b");
109                         var coalesce = Expression.Lambda<Func<string, string, string>> (
110                                 Expression.Coalesce (a, b), a, b).Compile ();
111
112                         Assert.AreEqual ("foo", coalesce ("foo", "bar"));
113                         Assert.AreEqual (null, coalesce (null, null));
114                         Assert.AreEqual ("bar", coalesce (null, "bar"));
115                         Assert.AreEqual ("foo", coalesce ("foo", null));
116                 }
117
118                 [Test]
119                 [Category ("NotWorkingInterpreter")]
120                 public void CoalesceNullableToNonNullable ()
121                 {
122                         var a = Expression.Parameter (typeof (int?), "a");
123
124                         var node = Expression.Coalesce (a, Expression.Constant (99, typeof (int)));
125
126                         Assert.AreEqual (typeof (int), node.Type);
127                         Assert.IsFalse (node.IsLifted);
128                         Assert.IsFalse (node.IsLiftedToNull);
129
130                         var coalesce = Expression.Lambda<Func<int?, int>> (node, a).Compile ();
131
132                         Assert.AreEqual (5, coalesce (5));
133                         Assert.AreEqual (99, coalesce (null));
134                 }
135
136                 [Test]
137                 [Category ("NotWorkingInterpreter")]
138                 [Category ("NotDotNet")] // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=349822
139                 public void CoalesceUserDefinedConversion ()
140                 {
141                         var s = Expression.Parameter (typeof (string), "s");
142
143                         var coalesce = Expression.Lambda<Func<string, int>> (
144                                 Expression.Coalesce (
145                                         s,
146                                         Expression.Constant (42),
147                                         Expression.Lambda<Func<string, int>> (
148                                                 Expression.Call (typeof (int).GetMethod ("Parse", new [] { typeof (string) }), s), s)), s).Compile ();
149
150                         Assert.AreEqual (12, coalesce ("12"));
151                         Assert.AreEqual (42, coalesce (null));
152                 }
153
154                 struct Slot {
155                         int Value;
156
157                         public Slot (int v)
158                         {
159                                 Value = v;
160                         }
161
162                         public static implicit operator int (Slot s)
163                         {
164                                 return s.Value;
165                         }
166                 }
167
168                 [Test]
169                 // #12987
170                 [Category ("MobileNotWorking")]
171                 [Category ("NotWorkingInterpreter")]
172                 public void CoalesceNullableSlotIntoInteger ()
173                 {
174                         var s = Expression.Parameter (typeof (Slot?), "s");
175
176                         var method = typeof (Slot).GetMethod ("op_Implicit");
177
178                         var coalesce = Expression.Lambda<Func<Slot?, int>> (
179                                 Expression.Coalesce (
180                                         s,
181                                         Expression.Constant (-3),
182                                         Expression.Lambda (
183                                                 Expression.Convert (s, typeof (int), method),
184                                                 s)), s).Compile ();
185
186                         Assert.AreEqual (-3, coalesce (null));
187                         Assert.AreEqual (42, coalesce (new Slot (42)));
188                 }
189
190                 [Test]
191                 [ExpectedException (typeof (ArgumentException))]
192                 public void WrongCoalesceConversionParameterCount ()
193                 {
194                         var s = Expression.Parameter (typeof (string), "s");
195                         var p = Expression.Parameter (typeof (string), "foo");
196
197                         Expression.Coalesce (
198                                 s,
199                                 42.ToConstant (),
200                                 Expression.Lambda<Func<string, string, int>> (
201                                         Expression.Call (typeof (int).GetMethod ("Parse", new [] { typeof (string) }), s), s, p));
202
203                 }
204
205                 [Test]
206                 [ExpectedException (typeof (InvalidOperationException))]
207                 public void WrongCoalesceConversionParameterType ()
208                 {
209                         var s = Expression.Parameter (typeof (string), "s");
210                         var i = Expression.Parameter (typeof (int), "i");
211
212                         Expression.Coalesce (
213                                 s,
214                                 42.ToConstant (),
215                                 Expression.Lambda<Func<int, int>> (
216                                         i, i));
217
218                 }
219
220                 [Test]
221                 [ExpectedException (typeof (InvalidOperationException))]
222                 public void WrongCoalesceConversionReturnType ()
223                 {
224                         var s = Expression.Parameter (typeof (string), "s");
225
226                         Expression.Coalesce (
227                                 s,
228                                 42.ToConstant (),
229                                 Expression.Lambda<Func<string, string>> (
230                                         s, s));
231                 }
232
233                 [Test]
234                 [ExpectedException (typeof (ArgumentException))]
235                 public void CoalesceVoidUserDefinedConversion ()
236                 {
237                         var s = Expression.Parameter (typeof (string), "s");
238
239                         Expression.Coalesce (
240                                 s,
241                                 42.ToConstant (),
242                                 Expression.Lambda<Action<string>> (
243                                         Expression.Call (typeof (int).GetMethod ("Parse", new [] { typeof (string) }), s), s));
244                 }
245         }
246 }