1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using Xunit; 6 7 namespace System.Linq.Expressions.Tests 8 { 9 public class TypeIs : TypeBinaryTests 10 { 11 [Fact] NullExpression()12 public void NullExpression() 13 { 14 AssertExtensions.Throws<ArgumentNullException>("expression", () => Expression.TypeIs(null, typeof(int))); 15 } 16 17 [Fact] NullType()18 public void NullType() 19 { 20 Expression exp = Expression.Constant(0); 21 AssertExtensions.Throws<ArgumentNullException>("type", () => Expression.TypeIs(exp, null)); 22 } 23 24 [Fact] TypeByRef()25 public void TypeByRef() 26 { 27 Expression exp = Expression.Constant(0); 28 Type byRef = typeof(int).MakeByRefType(); 29 AssertExtensions.Throws<ArgumentException>("type", () => Expression.TypeIs(exp, byRef)); 30 } 31 32 [Theory, ClassData(typeof(CompilationTypes))] TypePointer(bool useInterpreter)33 public void TypePointer(bool useInterpreter) 34 { 35 Expression exp = Expression.Constant(0); 36 Type pointer = typeof(int*); 37 var test = Expression.TypeIs(exp, pointer); 38 var lambda = Expression.Lambda<Func<bool>>(test); 39 var func = lambda.Compile(useInterpreter); 40 Assert.False(func()); 41 } 42 43 [Fact] UnreadableExpression()44 public void UnreadableExpression() 45 { 46 Expression exp = Expression.Property(null, typeof(Unreadable<int>), "WriteOnly"); 47 AssertExtensions.Throws<ArgumentException>("expression", () => Expression.TypeIs(exp, typeof(int))); 48 } 49 50 [Fact] CannotReduce()51 public void CannotReduce() 52 { 53 Expression exp = Expression.TypeIs(Expression.Constant(0), typeof(int)); 54 Assert.False(exp.CanReduce); 55 Assert.Same(exp, exp.Reduce()); 56 AssertExtensions.Throws<ArgumentException>(null, () => exp.ReduceAndCheck()); 57 } 58 59 [Theory] 60 [MemberData(nameof(ExpressionAndTypeCombinations))] TypePropertyMatches(Expression expression, Type type)61 public void TypePropertyMatches(Expression expression, Type type) 62 { 63 Assert.Equal(type, Expression.TypeIs(expression, type).TypeOperand); 64 } 65 66 [Theory] 67 [MemberData(nameof(ExpressionAndTypeCombinations))] TypeIsBoolean(Expression expression, Type type)68 public void TypeIsBoolean(Expression expression, Type type) 69 { 70 Assert.Equal(typeof(bool), Expression.TypeIs(expression, type).Type); 71 } 72 73 [Theory] 74 [MemberData(nameof(ExpressionAndTypeCombinations))] NodeType(Expression expression, Type type)75 public void NodeType(Expression expression, Type type) 76 { 77 Assert.Equal(ExpressionType.TypeIs, Expression.TypeIs(expression, type).NodeType); 78 } 79 80 [Theory] 81 [MemberData(nameof(ExpressionAndTypeCombinations))] ExpressionIsThatPassed(Expression expression, Type type)82 public void ExpressionIsThatPassed(Expression expression, Type type) 83 { 84 Assert.Same(expression, Expression.TypeIs(expression, type).Expression); 85 } 86 87 [Theory] 88 [PerCompilationType(nameof(ExpressionAndTypeCombinations))] ExpressionEvaluationCompiled(Expression expression, Type type, bool useInterpreter)89 public void ExpressionEvaluationCompiled(Expression expression, Type type, bool useInterpreter) 90 { 91 bool expected = expression.Type == typeof(void) 92 ? type == typeof(void) 93 : type.IsInstanceOfType(Expression.Lambda<Func<object>>(Expression.Convert(expression, typeof(object))).Compile()()); 94 95 Assert.Equal(expected, Expression.Lambda<Func<bool>>(Expression.TypeIs(expression, type)).Compile(useInterpreter)()); 96 } 97 98 [Theory] 99 [PerCompilationType(nameof(ExpressionAndTypeCombinations))] ExpressionEvaluationWithParameter(Expression expression, Type type, bool useInterpreter)100 public void ExpressionEvaluationWithParameter(Expression expression, Type type, bool useInterpreter) 101 { 102 if (expression.Type == typeof(void)) 103 return; // Can't have void parameter. 104 105 bool expected = expression.Type == typeof(void) 106 ? type == typeof(void) 107 : type.IsInstanceOfType(Expression.Lambda<Func<object>>(Expression.Convert(expression, typeof(object))).Compile()()); 108 109 ParameterExpression param = Expression.Parameter(expression.Type); 110 111 Func<bool> func = Expression.Lambda<Func<bool>>( 112 Expression.Block( 113 new[] { param }, 114 Expression.Assign(param, expression), 115 Expression.TypeIs(param, type) 116 ) 117 ).Compile(useInterpreter); 118 119 Assert.Equal(expected, func()); 120 } 121 122 [Fact] UpdateSameReturnsSame()123 public void UpdateSameReturnsSame() 124 { 125 Expression expression = Expression.Constant(0); 126 TypeBinaryExpression typeExp = Expression.TypeIs(expression, typeof(int)); 127 Assert.Same(typeExp, typeExp.Update(expression)); 128 Assert.Same(typeExp, NoOpVisitor.Instance.Visit(typeExp)); 129 } 130 131 [Fact] UpdateNotSameReturnsNotSame()132 public void UpdateNotSameReturnsNotSame() 133 { 134 Expression expression = Expression.Constant(0); 135 TypeBinaryExpression typeExp = Expression.TypeIs(expression, typeof(int)); 136 Assert.NotSame(typeExp, typeExp.Update(Expression.Constant(0))); 137 } 138 139 [Fact] VisitHitsVisitTypeBinary()140 public void VisitHitsVisitTypeBinary() 141 { 142 TypeBinaryExpression expression = Expression.TypeIs(Expression.Constant(0), typeof(int)); 143 TypeBinaryVisitCheckingVisitor visitor = new TypeBinaryVisitCheckingVisitor(); 144 visitor.Visit(expression); 145 Assert.Same(expression, visitor.LastTypeBinaryVisited); 146 } 147 148 [Fact] ToStringTest()149 public void ToStringTest() 150 { 151 TypeBinaryExpression e = Expression.TypeIs(Expression.Parameter(typeof(object), "o"), typeof(string)); 152 Assert.Equal("(o Is String)", e.ToString()); 153 } 154 } 155 } 156