diff --git a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/TypeOperations.cs b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/TypeOperations.cs index d2bc3242c76f..13c563bb9191 100644 --- a/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/TypeOperations.cs +++ b/src/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/TypeOperations.cs @@ -308,7 +308,7 @@ public override int Run(InterpretedFrame frame) internal abstract class NegateInstruction : Instruction { - private static Instruction s_int16,s_int32,s_int64,s_UInt16,s_UInt32,s_single,s_double; + private static Instruction s_int16, s_int32, s_int64, s_single, s_double; public override int ConsumedStack { get { return 1; } } public override int ProducedStack { get { return 1; } } @@ -348,7 +348,7 @@ public override int Run(InterpretedFrame frame) } else { - frame.Push((Int16)unchecked(-(Int16)obj)); + frame.Push(unchecked((Int16)(-(Int16)obj))); } return +1; } @@ -365,41 +365,7 @@ public override int Run(InterpretedFrame frame) } else { - frame.Push((Int64)unchecked(-(Int64)obj)); - } - return +1; - } - } - - internal sealed class NegateUInt16 : NegateInstruction - { - public override int Run(InterpretedFrame frame) - { - object obj = frame.Pop(); - if (obj == null) - { - frame.Push(null); - } - else - { - frame.Push((Int16)unchecked(-(UInt16)obj)); - } - return +1; - } - } - - internal sealed class NegateUInt32 : NegateInstruction - { - public override int Run(InterpretedFrame frame) - { - object obj = frame.Pop(); - if (obj == null) - { - frame.Push(null); - } - else - { - frame.Push((Int32)unchecked(-(UInt32)obj)); + frame.Push(unchecked((Int64)(-(Int64)obj))); } return +1; } @@ -416,7 +382,7 @@ public override int Run(InterpretedFrame frame) } else { - frame.Push((Single)unchecked(-(Single)obj)); + frame.Push(unchecked((Single)(-(Single)obj))); } return +1; } @@ -433,7 +399,7 @@ public override int Run(InterpretedFrame frame) } else { - frame.Push((Double)unchecked(-(Double)obj)); + frame.Push(unchecked((Double)(-(Double)obj))); } return +1; } @@ -447,8 +413,6 @@ public static Instruction Create(Type type) case TypeCode.Int16: return s_int16 ?? (s_int16 = new NegateInt16()); case TypeCode.Int32: return s_int32 ?? (s_int32 = new NegateInt32()); case TypeCode.Int64: return s_int64 ?? (s_int64 = new NegateInt64()); - case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new NegateUInt16()); - case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new NegateUInt32()); case TypeCode.Single: return s_single ?? (s_single = new NegateSingle()); case TypeCode.Double: return s_double ?? (s_double = new NegateDouble()); @@ -465,7 +429,7 @@ public override string ToString() internal abstract class NegateCheckedInstruction : Instruction { - private static Instruction s_int16,s_int32,s_int64,s_UInt16,s_UInt32,s_single,s_double; + private static Instruction s_int16, s_int32, s_int64, s_single, s_double; public override int ConsumedStack { get { return 1; } } public override int ProducedStack { get { return 1; } } @@ -505,7 +469,7 @@ public override int Run(InterpretedFrame frame) } else { - frame.Push((Int16)checked(-(Int16)obj)); + frame.Push(checked((Int16)(-(Int16)obj))); } return +1; } @@ -522,46 +486,11 @@ public override int Run(InterpretedFrame frame) } else { - frame.Push((Int64)checked(-(Int64)obj)); + frame.Push(checked((Int64)(-(Int64)obj))); } return +1; } } - - internal sealed class NegateCheckedUInt16 : NegateCheckedInstruction - { - public override int Run(InterpretedFrame frame) - { - object obj = frame.Pop(); - if (obj == null) - { - frame.Push(null); - } - else - { - frame.Push((Int16)checked(-(UInt16)obj)); - } - return +1; - } - } - - internal sealed class NegateCheckedUInt32 : NegateCheckedInstruction - { - public override int Run(InterpretedFrame frame) - { - object obj = frame.Pop(); - if (obj == null) - { - frame.Push(null); - } - else - { - frame.Push((Int32)checked(-(UInt32)obj)); - } - return +1; - } - } - internal sealed class NegateCheckedSingle : NegateCheckedInstruction { public override int Run(InterpretedFrame frame) @@ -573,7 +502,7 @@ public override int Run(InterpretedFrame frame) } else { - frame.Push((Single)checked(-(Single)obj)); + frame.Push(checked((Single)(-(Single)obj))); } return +1; } @@ -590,7 +519,7 @@ public override int Run(InterpretedFrame frame) } else { - frame.Push((Double)checked(-(Double)obj)); + frame.Push(checked((Double)(-(Double)obj))); } return +1; } @@ -604,8 +533,6 @@ public static Instruction Create(Type type) case TypeCode.Int16: return s_int16 ?? (s_int16 = new NegateCheckedInt16()); case TypeCode.Int32: return s_int32 ?? (s_int32 = new NegateCheckedInt32()); case TypeCode.Int64: return s_int64 ?? (s_int64 = new NegateCheckedInt64()); - case TypeCode.UInt16: return s_UInt16 ?? (s_UInt16 = new NegateCheckedUInt16()); - case TypeCode.UInt32: return s_UInt32 ?? (s_UInt32 = new NegateCheckedUInt32()); case TypeCode.Single: return s_single ?? (s_single = new NegateCheckedSingle()); case TypeCode.Double: return s_double ?? (s_double = new NegateCheckedDouble()); default: @@ -622,7 +549,7 @@ public override string ToString() internal abstract class IncrementInstruction : Instruction { - private static Instruction s_int16,s_int32,s_int64,s_UInt16,s_UInt32,s_single,s_double; + private static Instruction s_int16, s_int32, s_int64, s_UInt16, s_UInt32, s_single, s_double; public override int ConsumedStack { get { return 1; } } public override int ProducedStack { get { return 1; } } @@ -779,7 +706,7 @@ public override string ToString() internal abstract class DecrementInstruction : Instruction { - private static Instruction s_int16,s_int32,s_int64,s_UInt16,s_UInt32,s_single,s_double; + private static Instruction s_int16, s_int32, s_int64, s_UInt16, s_UInt32, s_single, s_double; public override int ConsumedStack { get { return 1; } } public override int ProducedStack { get { return 1; } } @@ -937,7 +864,7 @@ public override string ToString() internal abstract class LeftShiftInstruction : Instruction { - private static Instruction s_SByte,s_int16,s_int32,s_int64,s_byte,s_UInt16,s_UInt32,s_UInt64; + private static Instruction s_SByte, s_int16, s_int32, s_int64, s_byte, s_UInt16, s_UInt32, s_UInt64; public override int ConsumedStack { get { return 2; } } public override int ProducedStack { get { return 1; } } @@ -1122,7 +1049,7 @@ public override string ToString() internal abstract class RightShiftInstruction : Instruction { - private static Instruction s_SByte,s_int16,s_int32,s_int64,s_byte,s_UInt16,s_UInt32,s_UInt64; + private static Instruction s_SByte, s_int16, s_int32, s_int64, s_byte, s_UInt16, s_UInt32, s_UInt64; public override int ConsumedStack { get { return 2; } } public override int ProducedStack { get { return 1; } } @@ -1307,7 +1234,7 @@ public override string ToString() internal abstract class ExclusiveOrInstruction : Instruction { - private static Instruction s_SByte,s_int16,s_int32,s_int64,s_byte,s_UInt16,s_UInt32,s_UInt64,s_bool; + private static Instruction s_SByte, s_int16, s_int32, s_int64, s_byte, s_UInt16, s_UInt32, s_UInt64, s_bool; public override int ConsumedStack { get { return 2; } } public override int ProducedStack { get { return 1; } } @@ -1498,7 +1425,7 @@ public override string ToString() internal abstract class OrInstruction : Instruction { - private static Instruction s_SByte,s_int16,s_int32,s_int64,s_byte,s_UInt16,s_UInt32,s_UInt64,s_bool; + private static Instruction s_SByte, s_int16, s_int32, s_int64, s_byte, s_UInt16, s_UInt32, s_UInt64, s_bool; public override int ConsumedStack { get { return 2; } } public override int ProducedStack { get { return 1; } } @@ -1696,7 +1623,7 @@ public override string ToString() internal abstract class AndInstruction : Instruction { - private static Instruction s_SByte,s_int16,s_int32,s_int64,s_byte,s_UInt16,s_UInt32,s_UInt64,s_bool; + private static Instruction s_SByte, s_int16, s_int32, s_int64, s_byte, s_UInt16, s_UInt32, s_UInt64, s_bool; public override int ConsumedStack { get { return 2; } } public override int ProducedStack { get { return 1; } } @@ -2059,7 +1986,7 @@ public static Instruction CreateGetValue() internal abstract class CastInstruction : Instruction { - private static CastInstruction s_boolean,s_byte,s_char,s_dateTime,s_decimal,s_double,s_int16,s_int32,s_int64, s_SByte,s_single,s_string,s_UInt16,s_UInt32,s_UInt64; + private static CastInstruction s_boolean, s_byte, s_char, s_dateTime, s_decimal, s_double, s_int16, s_int32, s_int64, s_SByte, s_single, s_string, s_UInt16, s_UInt32, s_UInt64; public override int ConsumedStack { get { return 1; } } public override int ProducedStack { get { return 1; } } diff --git a/src/System.Linq.Expressions/tests/System.Linq.Expressions.Tests.csproj b/src/System.Linq.Expressions/tests/System.Linq.Expressions.Tests.csproj index 61e670f403bf..45ab4513051f 100644 --- a/src/System.Linq.Expressions/tests/System.Linq.Expressions.Tests.csproj +++ b/src/System.Linq.Expressions/tests/System.Linq.Expressions.Tests.csproj @@ -133,7 +133,9 @@ + + diff --git a/src/System.Linq.Expressions/tests/Unary/UnaryArithmeticNegateCheckedNullableTests.cs b/src/System.Linq.Expressions/tests/Unary/UnaryArithmeticNegateCheckedNullableTests.cs new file mode 100644 index 000000000000..897884b2928b --- /dev/null +++ b/src/System.Linq.Expressions/tests/Unary/UnaryArithmeticNegateCheckedNullableTests.cs @@ -0,0 +1,402 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Linq; +using System.Linq.Expressions; +using Xunit; + +namespace Tests.ExpressionCompiler.Unary +{ + public static unsafe class UnaryArithmeticNegateCheckedNullableTests + { + #region Test methods + + [Fact] + public static void CheckUnaryArithmeticNegateCheckedNullableByteTest() + { + byte?[] values = new byte?[] { null, 0, 1, byte.MaxValue }; + for (int i = 0; i < values.Length; i++) + { + VerifyArithmeticNegateCheckedNullableByte(values[i]); + } + } + + [Fact] + public static void CheckUnaryArithmeticNegateCheckedNullableCharTest() + { + char?[] values = new char?[] { null, '\0', '\b', 'A', '\uffff' }; + for (int i = 0; i < values.Length; i++) + { + VerifyArithmeticNegateCheckedNullableChar(values[i]); + } + } + + [Fact] + public static void CheckUnaryArithmeticNegateCheckedNullableDecimalTest() + { + decimal?[] values = new decimal?[] { null, decimal.Zero, decimal.One, decimal.MinusOne, decimal.MinValue, decimal.MaxValue }; + for (int i = 0; i < values.Length; i++) + { + VerifyArithmeticNegateCheckedNullableDecimal(values[i]); + } + } + + [Fact] + public static void CheckUnaryArithmeticNegateCheckedNullableDoubleTest() + { + double?[] values = new double?[] { null, 0, 1, -1, double.MinValue, double.MaxValue, double.Epsilon, double.NegativeInfinity, double.PositiveInfinity, double.NaN }; + for (int i = 0; i < values.Length; i++) + { + VerifyArithmeticNegateCheckedNullableDouble(values[i]); + } + } + + [Fact] + public static void CheckUnaryArithmeticNegateCheckedNullableFloatTest() + { + float?[] values = new float?[] { null, 0, 1, -1, float.MinValue, float.MaxValue, float.Epsilon, float.NegativeInfinity, float.PositiveInfinity, float.NaN }; + for (int i = 0; i < values.Length; i++) + { + VerifyArithmeticNegateCheckedNullableFloat(values[i]); + } + } + + [Fact] + public static void CheckUnaryArithmeticNegateCheckedNullableIntTest() + { + int?[] values = new int?[] { null, 0, 1, -1, int.MinValue, int.MaxValue }; + for (int i = 0; i < values.Length; i++) + { + VerifyArithmeticNegateCheckedNullableInt(values[i]); + } + } + + [Fact] + public static void CheckUnaryArithmeticNegateCheckedNullableLongTest() + { + long?[] values = new long?[] { null, 0, 1, -1, long.MinValue, long.MaxValue }; + for (int i = 0; i < values.Length; i++) + { + VerifyArithmeticNegateCheckedNullableLong(values[i]); + } + } + + [Fact] + public static void CheckUnaryArithmeticNegateCheckedNullableSByteTest() + { + sbyte?[] values = new sbyte?[] { null, 0, 1, -1, sbyte.MinValue, sbyte.MaxValue }; + for (int i = 0; i < values.Length; i++) + { + VerifyArithmeticNegateCheckedNullableSByte(values[i]); + } + } + + [Fact] + public static void CheckUnaryArithmeticNegateCheckedNullableShortTest() + { + short?[] values = new short?[] { null, 0, 1, -1, short.MinValue, short.MaxValue }; + for (int i = 0; i < values.Length; i++) + { + VerifyArithmeticNegateCheckedNullableShort(values[i]); + } + } + + #endregion + + #region Test verifiers + + private static void VerifyArithmeticNegateCheckedNullableByte(byte? value) + { + Assert.Throws(() => Expression.NegateChecked(Expression.Constant(value, typeof(byte?)))); + } + + private static void VerifyArithmeticNegateCheckedNullableChar(char? value) + { + Assert.Throws(() => Expression.NegateChecked(Expression.Constant(value, typeof(char?)))); + } + + private static void VerifyArithmeticNegateCheckedNullableDecimal(decimal? value) + { + Expression> e = + Expression.Lambda>( + Expression.NegateChecked(Expression.Constant(value, typeof(decimal?))), + Enumerable.Empty()); + + Func f = e.Compile(); + + // add with expression tree + decimal? etResult = default(decimal?); + Exception etException = null; + try + { + etResult = f(); + } + catch (Exception ex) + { + etException = ex; + } + + // add with real IL + decimal? csResult = default(decimal?); + Exception csException = null; + try + { + csResult = checked((decimal?)(-value)); + } + catch (Exception ex) + { + csException = ex; + } + + // either both should have failed the same way or they should both produce the same result + if (etException != null || csException != null) + { + Assert.NotNull(etException); + Assert.NotNull(csException); + Assert.Equal(csException.GetType(), etException.GetType()); + } + else + { + Assert.Equal(csResult, etResult); + } + } + + private static void VerifyArithmeticNegateCheckedNullableDouble(double? value) + { + Expression> e = + Expression.Lambda>( + Expression.NegateChecked(Expression.Constant(value, typeof(double?))), + Enumerable.Empty()); + + Func f = e.Compile(); + + // add with expression tree + double? etResult = default(double?); + Exception etException = null; + try + { + etResult = f(); + } + catch (Exception ex) + { + etException = ex; + } + + // add with real IL + double? csResult = default(double?); + Exception csException = null; + try + { + csResult = checked((double?)(-value)); + } + catch (Exception ex) + { + csException = ex; + } + + // either both should have failed the same way or they should both produce the same result + if (etException != null || csException != null) + { + Assert.NotNull(etException); + Assert.NotNull(csException); + Assert.Equal(csException.GetType(), etException.GetType()); + } + else + { + Assert.Equal(csResult, etResult); + } + } + + private static void VerifyArithmeticNegateCheckedNullableFloat(float? value) + { + Expression> e = + Expression.Lambda>( + Expression.NegateChecked(Expression.Constant(value, typeof(float?))), + Enumerable.Empty()); + + Func f = e.Compile(); + + // add with expression tree + float? etResult = default(float?); + Exception etException = null; + try + { + etResult = f(); + } + catch (Exception ex) + { + etException = ex; + } + + // add with real IL + float? csResult = default(float?); + Exception csException = null; + try + { + csResult = checked((float?)(-value)); + } + catch (Exception ex) + { + csException = ex; + } + + // either both should have failed the same way or they should both produce the same result + if (etException != null || csException != null) + { + Assert.NotNull(etException); + Assert.NotNull(csException); + Assert.Equal(csException.GetType(), etException.GetType()); + } + else + { + Assert.Equal(csResult, etResult); + } + } + + private static void VerifyArithmeticNegateCheckedNullableInt(int? value) + { + Expression> e = + Expression.Lambda>( + Expression.NegateChecked(Expression.Constant(value, typeof(int?))), + Enumerable.Empty()); + + Func f = e.Compile(); + + // add with expression tree + int? etResult = default(int?); + Exception etException = null; + try + { + etResult = f(); + } + catch (Exception ex) + { + etException = ex; + } + + // add with real IL + int? csResult = default(int?); + Exception csException = null; + try + { + csResult = checked((int?)(-value)); + } + catch (Exception ex) + { + csException = ex; + } + + // either both should have failed the same way or they should both produce the same result + if (etException != null || csException != null) + { + Assert.NotNull(etException); + Assert.NotNull(csException); + Assert.Equal(csException.GetType(), etException.GetType()); + } + else + { + Assert.Equal(csResult, etResult); + } + } + + private static void VerifyArithmeticNegateCheckedNullableLong(long? value) + { + Expression> e = + Expression.Lambda>( + Expression.NegateChecked(Expression.Constant(value, typeof(long?))), + Enumerable.Empty()); + + Func f = e.Compile(); + + // add with expression tree + long? etResult = default(long?); + Exception etException = null; + try + { + etResult = f(); + } + catch (Exception ex) + { + etException = ex; + } + + // add with real IL + long? csResult = default(long?); + Exception csException = null; + try + { + csResult = checked((long?)(-value)); + } + catch (Exception ex) + { + csException = ex; + } + + // either both should have failed the same way or they should both produce the same result + if (etException != null || csException != null) + { + Assert.NotNull(etException); + Assert.NotNull(csException); + Assert.Equal(csException.GetType(), etException.GetType()); + } + else + { + Assert.Equal(csResult, etResult); + } + } + + private static void VerifyArithmeticNegateCheckedNullableSByte(sbyte? value) + { + Assert.Throws(() => Expression.NegateChecked(Expression.Constant(value, typeof(sbyte?)))); + } + + private static void VerifyArithmeticNegateCheckedNullableShort(short? value) + { + Expression> e = + Expression.Lambda>( + Expression.NegateChecked(Expression.Constant(value, typeof(short?))), + Enumerable.Empty()); + + Func f = e.Compile(); + + // add with expression tree + short? etResult = default(short?); + Exception etException = null; + try + { + etResult = f(); + } + catch (Exception ex) + { + etException = ex; + } + + // add with real IL + short? csResult = default(short?); + Exception csException = null; + try + { + csResult = checked((short?)(-value)); + } + catch (Exception ex) + { + csException = ex; + } + + // either both should have failed the same way or they should both produce the same result + if (etException != null || csException != null) + { + Assert.NotNull(etException); + Assert.NotNull(csException); + Assert.Equal(csException.GetType(), etException.GetType()); + } + else + { + Assert.Equal(csResult, etResult); + } + } + + #endregion + } +} diff --git a/src/System.Linq.Expressions/tests/Unary/UnaryArithmeticNegateCheckedTests.cs b/src/System.Linq.Expressions/tests/Unary/UnaryArithmeticNegateCheckedTests.cs new file mode 100644 index 000000000000..1669f3cb7030 --- /dev/null +++ b/src/System.Linq.Expressions/tests/Unary/UnaryArithmeticNegateCheckedTests.cs @@ -0,0 +1,402 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Linq; +using System.Linq.Expressions; +using Xunit; + +namespace Tests.ExpressionCompiler.Unary +{ + public static unsafe class UnaryArithmeticNegateCheckedTests + { + #region Test methods + + [Fact] + public static void CheckUnaryArithmeticNegateCheckedByteTest() + { + byte[] values = new byte[] { 0, 1, byte.MaxValue }; + for (int i = 0; i < values.Length; i++) + { + VerifyArithmeticNegateCheckedByte(values[i]); + } + } + + [Fact] + public static void CheckUnaryArithmeticNegateCheckedCharTest() + { + char[] values = new char[] { '\0', '\b', 'A', '\uffff' }; + for (int i = 0; i < values.Length; i++) + { + VerifyArithmeticNegateCheckedChar(values[i]); + } + } + + [Fact] + public static void CheckUnaryArithmeticNegateCheckedDecimalTest() + { + decimal[] values = new decimal[] { decimal.Zero, decimal.One, decimal.MinusOne, decimal.MinValue, decimal.MaxValue }; + for (int i = 0; i < values.Length; i++) + { + VerifyArithmeticNegateCheckedDecimal(values[i]); + } + } + + [Fact] + public static void CheckUnaryArithmeticNegateCheckedDoubleTest() + { + double[] values = new double[] { 0, 1, -1, double.MinValue, double.MaxValue, double.Epsilon, double.NegativeInfinity, double.PositiveInfinity, double.NaN }; + for (int i = 0; i < values.Length; i++) + { + VerifyArithmeticNegateCheckedDouble(values[i]); + } + } + + [Fact] + public static void CheckUnaryArithmeticNegateCheckedFloatTest() + { + float[] values = new float[] { 0, 1, -1, float.MinValue, float.MaxValue, float.Epsilon, float.NegativeInfinity, float.PositiveInfinity, float.NaN }; + for (int i = 0; i < values.Length; i++) + { + VerifyArithmeticNegateCheckedFloat(values[i]); + } + } + + [Fact] + public static void CheckUnaryArithmeticNegateCheckedIntTest() + { + int[] values = new int[] { 0, 1, -1, int.MinValue, int.MaxValue }; + for (int i = 0; i < values.Length; i++) + { + VerifyArithmeticNegateCheckedInt(values[i]); + } + } + + [Fact] + public static void CheckUnaryArithmeticNegateCheckedLongTest() + { + long[] values = new long[] { 0, 1, -1, long.MinValue, long.MaxValue }; + for (int i = 0; i < values.Length; i++) + { + VerifyArithmeticNegateCheckedLong(values[i]); + } + } + + [Fact] + public static void CheckUnaryArithmeticNegateCheckedSByteTest() + { + sbyte[] values = new sbyte[] { 0, 1, -1, sbyte.MinValue, sbyte.MaxValue }; + for (int i = 0; i < values.Length; i++) + { + VerifyArithmeticNegateCheckedSByte(values[i]); + } + } + + [Fact] + public static void CheckUnaryArithmeticNegateCheckedShortTest() + { + short[] values = new short[] { 0, 1, -1, short.MinValue, short.MaxValue }; + for (int i = 0; i < values.Length; i++) + { + VerifyArithmeticNegateCheckedShort(values[i]); + } + } + + #endregion + + #region Test verifiers + + private static void VerifyArithmeticNegateCheckedByte(byte value) + { + Assert.Throws(() => Expression.NegateChecked(Expression.Constant(value, typeof(byte)))); + } + + private static void VerifyArithmeticNegateCheckedChar(char value) + { + Assert.Throws(() => Expression.NegateChecked(Expression.Constant(value, typeof(char)))); + } + + private static void VerifyArithmeticNegateCheckedDecimal(decimal value) + { + Expression> e = + Expression.Lambda>( + Expression.NegateChecked(Expression.Constant(value, typeof(decimal))), + Enumerable.Empty()); + + Func f = e.Compile(); + + // add with expression tree + decimal etResult = default(decimal); + Exception etException = null; + try + { + etResult = f(); + } + catch (Exception ex) + { + etException = ex; + } + + // add with real IL + decimal csResult = default(decimal); + Exception csException = null; + try + { + csResult = checked((decimal)(-value)); + } + catch (Exception ex) + { + csException = ex; + } + + // either both should have failed the same way or they should both produce the same result + if (etException != null || csException != null) + { + Assert.NotNull(etException); + Assert.NotNull(csException); + Assert.Equal(csException.GetType(), etException.GetType()); + } + else + { + Assert.Equal(csResult, etResult); + } + } + + private static void VerifyArithmeticNegateCheckedDouble(double value) + { + Expression> e = + Expression.Lambda>( + Expression.NegateChecked(Expression.Constant(value, typeof(double))), + Enumerable.Empty()); + + Func f = e.Compile(); + + // add with expression tree + double etResult = default(double); + Exception etException = null; + try + { + etResult = f(); + } + catch (Exception ex) + { + etException = ex; + } + + // add with real IL + double csResult = default(double); + Exception csException = null; + try + { + csResult = checked((double)(-value)); + } + catch (Exception ex) + { + csException = ex; + } + + // either both should have failed the same way or they should both produce the same result + if (etException != null || csException != null) + { + Assert.NotNull(etException); + Assert.NotNull(csException); + Assert.Equal(csException.GetType(), etException.GetType()); + } + else + { + Assert.Equal(csResult, etResult); + } + } + + private static void VerifyArithmeticNegateCheckedFloat(float value) + { + Expression> e = + Expression.Lambda>( + Expression.NegateChecked(Expression.Constant(value, typeof(float))), + Enumerable.Empty()); + + Func f = e.Compile(); + + // add with expression tree + float etResult = default(float); + Exception etException = null; + try + { + etResult = f(); + } + catch (Exception ex) + { + etException = ex; + } + + // add with real IL + float csResult = default(float); + Exception csException = null; + try + { + csResult = checked((float)(-value)); + } + catch (Exception ex) + { + csException = ex; + } + + // either both should have failed the same way or they should both produce the same result + if (etException != null || csException != null) + { + Assert.NotNull(etException); + Assert.NotNull(csException); + Assert.Equal(csException.GetType(), etException.GetType()); + } + else + { + Assert.Equal(csResult, etResult); + } + } + + private static void VerifyArithmeticNegateCheckedInt(int value) + { + Expression> e = + Expression.Lambda>( + Expression.NegateChecked(Expression.Constant(value, typeof(int))), + Enumerable.Empty()); + + Func f = e.Compile(); + + // add with expression tree + int etResult = default(int); + Exception etException = null; + try + { + etResult = f(); + } + catch (Exception ex) + { + etException = ex; + } + + // add with real IL + int csResult = default(int); + Exception csException = null; + try + { + csResult = checked((int)(-value)); + } + catch (Exception ex) + { + csException = ex; + } + + // either both should have failed the same way or they should both produce the same result + if (etException != null || csException != null) + { + Assert.NotNull(etException); + Assert.NotNull(csException); + Assert.Equal(csException.GetType(), etException.GetType()); + } + else + { + Assert.Equal(csResult, etResult); + } + } + + private static void VerifyArithmeticNegateCheckedLong(long value) + { + Expression> e = + Expression.Lambda>( + Expression.NegateChecked(Expression.Constant(value, typeof(long))), + Enumerable.Empty()); + + Func f = e.Compile(); + + // add with expression tree + long etResult = default(long); + Exception etException = null; + try + { + etResult = f(); + } + catch (Exception ex) + { + etException = ex; + } + + // add with real IL + long csResult = default(long); + Exception csException = null; + try + { + csResult = checked((long)(-value)); + } + catch (Exception ex) + { + csException = ex; + } + + // either both should have failed the same way or they should both produce the same result + if (etException != null || csException != null) + { + Assert.NotNull(etException); + Assert.NotNull(csException); + Assert.Equal(csException.GetType(), etException.GetType()); + } + else + { + Assert.Equal(csResult, etResult); + } + } + + private static void VerifyArithmeticNegateCheckedSByte(sbyte value) + { + Assert.Throws(() => Expression.NegateChecked(Expression.Constant(value, typeof(sbyte)))); + } + + private static void VerifyArithmeticNegateCheckedShort(short value) + { + Expression> e = + Expression.Lambda>( + Expression.NegateChecked(Expression.Constant(value, typeof(short))), + Enumerable.Empty()); + + Func f = e.Compile(); + + // add with expression tree + short etResult = default(short); + Exception etException = null; + try + { + etResult = f(); + } + catch (Exception ex) + { + etException = ex; + } + + // add with real IL + short csResult = default(short); + Exception csException = null; + try + { + csResult = checked((short)(-value)); + } + catch (Exception ex) + { + csException = ex; + } + + // either both should have failed the same way or they should both produce the same result + if (etException != null || csException != null) + { + Assert.NotNull(etException); + Assert.NotNull(csException); + Assert.Equal(csException.GetType(), etException.GetType()); + } + else + { + Assert.Equal(csResult, etResult); + } + } + + #endregion + } +}