using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; // Dynamic binary and unary operators tests public struct InverseLogicalOperator { bool value; public InverseLogicalOperator (bool value) { this.value = value; } public static bool operator true (InverseLogicalOperator u) { return u.value; } public static bool operator false (InverseLogicalOperator u) { return u.value; } } // TODO: Create a clone which uses +(MyType, int) pattern and an implicit conversion // is required to do the user-conversion public struct MyType { int value; public MyType (int value) : this () { this.value = value; } public short ShortProp { get; set; } public override int GetHashCode () { throw new NotImplementedException (); } public static implicit operator int (MyType o) { return o.value; } public static bool operator true (MyType a) { return a.value == a; } public static bool operator false (MyType a) { return a.value != a; } public static MyType operator + (MyType a, MyType b) { return new MyType (a.value + b.value); } public static MyType operator - (MyType a, MyType b) { return new MyType (a.value - b.value); } public static MyType operator / (MyType a, MyType b) { return new MyType (a.value / b.value); } public static MyType operator * (MyType a, MyType b) { return new MyType (a.value * b.value); } public static MyType operator % (MyType a, MyType b) { return new MyType (a.value % b.value); } public static MyType operator &(MyType a, MyType b) { return new MyType (a.value & b.value); } public static MyType operator | (MyType a, MyType b) { return new MyType (a.value | b.value); } public static MyType operator ^ (MyType a, MyType b) { return new MyType (a.value ^ b.value); } public static bool operator == (MyType a, MyType b) { return a.value == b.value; } public static bool operator != (MyType a, MyType b) { return a.value != b.value; } public static bool operator > (MyType a, MyType b) { return a.value > b.value; } public static bool operator < (MyType a, MyType b) { return a.value < b.value; } public static bool operator >= (MyType a, MyType b) { return a.value >= b.value; } public static bool operator <= (MyType a, MyType b) { return a.value <= b.value; } public static bool operator ! (MyType a) { return a.value > 0; } public static int operator >> (MyType a, int b) { return a.value >> b; } public static int operator << (MyType a, int b) { return a.value << b; } public static MyType operator - (MyType a) { return new MyType (-a.value); } public static MyType operator + (MyType a) { return new MyType (+a.value); } public override string ToString () { return value.ToString (); } } class MyTypeExplicit { int value; public MyTypeExplicit (int value) { this.value = value; } public static explicit operator int (MyTypeExplicit m) { return m.value; } } struct MyTypeImplicitOnly { short b; public MyTypeImplicitOnly (short b) { this.b = b; } public static implicit operator short (MyTypeImplicitOnly m) { return m.b; } } enum MyEnum : byte { Value_1 = 1, Value_2 = 2 } enum MyEnumUlong : ulong { Value_1 = 1, Value_2 = 2 } class Tester { delegate void EmptyDelegate (); delegate int IntDelegate (); static void Assert (T expected, T value, string name) { if (!EqualityComparer.Default.Equals (expected, value)) { name += ": "; throw new ApplicationException (name + expected + " != " + value); } } static void AssertChecked (Func expected, T value, string name) { try { Assert (expected (), value, name); throw new ApplicationException (name + ": OverflowException expected"); } catch (OverflowException) { // passed } } static void AssertChecked (Action expected, string name) { try { expected (); throw new ApplicationException (name + ": OverflowException expected"); } catch (OverflowException) { // passed } } #pragma warning disable 169 void AddTest () { dynamic d = 5; int v = 2; Assert (d + v, 7, "#1"); double v2 = 0.5; Assert (d + v2, 5.5, "#1a"); MyType v3 = new MyType (30); Assert (d + v3, new MyType (35), "#3"); dynamic d3 = new MyType (-7); Assert (d3 + new MyType (6), new MyType (-1), "#3a"); Assert (d3 + 11, 4, "#3b"); decimal v4 = 4m; Assert (d + v4, 9m, "#4"); } void AddNullableTest () { dynamic d = 5; int? v2 = null; Assert (d + v2, null, "#1"); Assert (d + null, null, "#1a"); Assert (null + d, null, "#1b"); v2 = -2; Assert (d + v2, 3, "#2"); dynamic d2 = (int?) -2; Assert (d2 + 1, -1, "#2a"); MyType? v3 = new MyType (30); Assert (d + v3, new MyType (35), "#3"); dynamic d3 = new MyType? (new MyType (-7)); Assert (d3 + new MyType (6), new MyType (-1), "#3a"); Assert (d3 + null, null, "#3b"); decimal? v4 = 4m; Assert (d + v4, 9m, "#4"); v4 = null; Assert (d + v4, null, "#4a"); } void AddEnumTest () { dynamic d = MyEnum.Value_1; // CSC: Invalid System.InvalidOperationException Assert (d + null, null, "#1"); Assert (d + 1, MyEnum.Value_2, "#2"); dynamic d2 = (MyEnumUlong?) MyEnumUlong.Value_1; Assert (d2 + (byte) 1, MyEnumUlong.Value_2, "#3"); Assert (d2 + (object) null, null, "#3a"); } void AddCheckedTest () { checked { dynamic d = 5; int v = int.MaxValue; AssertChecked (() => d + v, 7, "#1"); int? v2 = v; AssertChecked (() => d + v2, null, "#2"); MyType v3 = new MyType (int.MaxValue); AssertChecked (() => d + v3, new MyType (35), "#3"); } } void AddStringTest () { dynamic d = "foo"; string v = "->"; Assert (d + v, "foo->", "#1"); Assert (d + 1, "foo1", "#1a"); Assert (d + null, "foo", "#1b"); Assert (d + 1 + v, "foo1->", "#1a"); uint? v2 = 4; Assert (d + v2, "foo4", "#2"); } void AddAssignTest () { dynamic d = 5; int v = 2; d += v; Assert (d, 7, "#1"); d = 5.0; double v2 = 0.5; d += v2; Assert (d, 5.5, "#1a"); d += v; Assert (d, 7.5, "#1b"); dynamic d3 = new MyType (-7); d3 += new MyType (6); Assert (d3, new MyType (-1), "#3"); d = 5m; decimal v4 = 4m; d += v4; Assert (d, 9m, "#4"); } void AddAssignNullableTest () { dynamic d = (int?) 5; // FEATURE // For now it's impossible to use nullable compound assignment // due to the way how DLR works. GetType () on nullable object returns // underlying type and not nullable type, that means that // C# binder is initialized with wrong operand type and any operation // fails to resolve /* long? v2 = null; d += v2; Assert (d, null, "#1"); d += null; Assert (d, null, "#1a"); long? l = (long?) 3; d = l; v2 = -2; d += v2; Assert (d, 3, "#2"); d = (int?) -2; d += 1; Assert (d, -1, "#2a"); MyType? v3 = new MyType (30); d += v3; Assert (d, new MyType (35), "#3"); dynamic d3 = new MyType? (new MyType (-7)); Assert (d3 + new MyType (6), new MyType (-1), "#3a"); Assert (d3 + null, null, "#3b"); decimal? v4 = 4m; d = 2m; d += v4; Assert (d, 9m, "#4"); d += null; Assert (d, null, "#4a"); */ } void AddAssignEnumTest () { dynamic d = MyEnum.Value_1; d = MyEnum.Value_1; d += 1; Assert (d, MyEnum.Value_2, "#2"); dynamic d2 = (MyEnumUlong?) MyEnumUlong.Value_1; d2 += (byte) 1; Assert (d2, MyEnumUlong.Value_2, "#3"); } void AddAssignCheckedTest () { checked { dynamic d = 5; int v = int.MaxValue; AssertChecked (() => { d += v; Assert (d, 0, "#1-"); }, "#1"); MyType v3 = new MyType (int.MaxValue); AssertChecked (() => { d += v3; Assert (d, 0, "#3-"); }, "#3"); } } void AddAssignStringTest () { dynamic d = "foo"; string v = "->"; d += v; Assert (d, "foo->", "#1"); d = "foo"; d += 1; Assert (d, "foo1", "#1a"); d += null; Assert (d, "foo1", "#1b"); uint? v2 = 4; d = "foo"; d += v2; Assert (d, "foo4", "#2"); } // TODO: void AddAssignmentEvent () { // IMPLEMENT } void AndTest () { dynamic d = true; var v = false; Assert (d & v, false, "#1"); Assert (d & true, true, "#1a"); d = 42; var v2 = 62; Assert (d & v2, 42, "#2"); Assert (d & 0, 0, "#2a"); MyType v3 = new MyType (30); Assert (d & v3, new MyType (10), "#3"); dynamic d3 = new MyType (-7); Assert (d3 & new MyType (6), new MyType (0), "#3a"); Assert (d3 & 11, 9, "#3b"); } void AndTestEnum () { dynamic d = MyEnum.Value_1; Assert (d & null, null, "#1"); Assert (d & d, MyEnum.Value_1, "#2"); dynamic d2 = (MyEnumUlong?) MyEnumUlong.Value_1; Assert (d2 & MyEnumUlong.Value_2, 0, "#3"); } void AndTestNullable () { dynamic d = 5; int? v2 = null; Assert (d & v2, null, "#1"); Assert (d & null, null, "#1a"); Assert (null & d, null, "#1b"); v2 = -2; Assert (d & v2, 4, "#2"); dynamic d2 = (int?) -2; Assert (d2 & 1, 0, "#2a"); MyType? v3 = new MyType (30); Assert (d & v3, new MyType (4), "#3"); dynamic d3 = new MyType? (new MyType (-7)); Assert (d3 & new MyType (6), new MyType (0), "#3a"); Assert (d3 + null, null, "#3b"); } void AndAssignedTest () { dynamic d = true; var v = false; d &= v; Assert (d, false, "#1"); d = true; d &= true; Assert (d, true, "#1a"); d = 42; var v2 = 62; d &= v2; Assert (d, 42, "#2"); MyType v3 = new MyType (30); dynamic d3 = new MyType (-7); d3 &= new MyType (6); Assert (d3, new MyType (0), "#3"); } void AndAssignedTestEnum () { dynamic d = MyEnum.Value_1; d &= MyEnum.Value_2; Assert(d, 0, "#1"); d = MyEnum.Value_2; d &= d; Assert (d, MyEnum.Value_2, "#2"); dynamic d2 = (MyEnumUlong?) MyEnumUlong.Value_1; Assert (d2 & MyEnumUlong.Value_2, 0, "#3"); } void AndAlsoTest () { dynamic d = true; var v = false; Assert (d && v, false, "#1"); Assert (d && true, true, "#1a"); d = true; Assert (d && d, true, "#2"); dynamic d3 = new MyType (-7); Assert (d3 && new MyType (6), new MyType (0), "#3"); // This should not compile Assert (d3 && 11, 9, "#3b"); } void DivideTest () { dynamic d = 5; int v = 2; Assert (d / v, 2, "#1"); MyType v3 = new MyType (30); Assert (d / v3, new MyType (0), "#3"); dynamic d3 = new MyType (-7); Assert (d3 + new MyType (6), new MyType (-1), "#3a"); Assert (d3 / 11, 0, "#3b"); decimal v4 = 4m; Assert (d / v4, 1.25m, "#4"); } void DivideNullableTest () { dynamic d = 5; double? v2 = null; Assert (d / v2, null, "#1"); Assert (d / null, null, "#1a"); Assert (null / d, null, "#1b"); v2 = -2; Assert (d / v2, -2.5, "#2"); dynamic d2 = (int?) -2; Assert (d2 / 1, -2, "#2a"); MyType? v3 = new MyType (30); Assert (d / v3, new MyType (0), "#3"); dynamic d3 = new MyType? (new MyType (-7)); Assert (d3 / new MyType (6), new MyType (-1), "#3a"); Assert (d3 + null, null, "#3b"); decimal? v4 = 4m; Assert (d / v4, 1.25m, "#4"); v4 = null; Assert (d / v4, null, "#4a"); } void DivideCheckedTest () { checked { // TODO: } } void DivideAssignTest () { dynamic d = 5; int v = 2; d /= v; Assert (d, 2, "#1"); d = 5.0; double v2 = 0.5; d /= v2; Assert (d, 10, "#1a"); d /= v; Assert (d, 5, "#1b"); dynamic d3 = new MyType (-7); d3 /= new MyType (6); Assert (d3, new MyType (-1), "#3"); d = 5m; decimal v4 = 4m; d /= v4; Assert (d, 1.25m, "#4"); } void DivideAssignCheckedTest () { checked { // TODO: } } void EqualTest () { dynamic d = 5; int v = 2; Assert (d == v, false, "#1"); double v2 = 5; Assert (d == v2, true, "#1a"); d = true; Assert (d == false, false, "#2"); bool b2 = true; Assert (d == b2, true, "#2a"); d = new MyType (30); MyType v3 = new MyType (30); Assert (d == v3, true, "#3"); dynamic d3 = new MyType (-7); Assert (d3 == new MyType (6), false, "#3a"); Assert (d3 == 11, false, "#3b"); d = 2m; decimal v4 = 4m; Assert (d == v4, false, "#4"); Assert (d == 2m, true, "#4a"); d = null; Assert (d == null, true, "#5"); } void EqualNullableTest () { dynamic d = 5; int? v2 = null; Assert (d == v2, false, "#1"); Assert (d == null, false, "#1a"); Assert (null == d, false, "#1b"); v2 = -2; Assert (d == v2, false, "#2"); dynamic d2 = (int?) -2; Assert (d2 == 1, false, "#2a"); d2 = (uint?) 44; Assert (d2 == 44, true, "#2b"); d = new MyType (30); MyType? v3 = new MyType (30); Assert (d == v3, true, "#3"); dynamic d3 = new MyType? (new MyType (-7)); Assert (d3 == new MyType (6), false, "#3a"); Assert (d3 == null, false, "#3b"); d = 4.1m; decimal? v4 = 4m; Assert (d == v4, false, "#4"); v4 = null; Assert (d == v4, false, "#4a"); d = (bool?) true; Assert (d == true, true, "#5"); Assert (d == null, false, "#5a"); Assert (d == false, false, "#5b"); } void EqualEnumTest () { dynamic d = MyEnum.Value_1; Assert (d == null, false, "#1"); Assert (d == MyEnum.Value_1, true, "#2"); Assert (d == 0, false, "#2a"); dynamic d2 = (MyEnumUlong?) MyEnumUlong.Value_2; Assert (d2 == MyEnumUlong.Value_2, true, "#3"); Assert (d2 == null, false, "#3a"); } void EqualStringTest () { dynamic d = "text"; Assert (d == "te", false, "#1"); Assert (d == "text", true, "#1a"); Assert (d == null, false, "#1b"); } void EqualDelegateTest () { dynamic d = this; // Assert (d == delegate { }, true, "#1"); EmptyDelegate b = EqualDelegateTest; d = b; //Assert (d == EqualDelegateTest, true, "#2"); /* void EqualTestDelegate_2 () { EmptyDelegate ed = delegate () {}; Expression> e2 = (a, b) => a == b; AssertNodeType (e2, ExpressionType.Equal); Assert (false, e2.Compile ().Invoke (delegate () {}, null)); Assert (false, e2.Compile ().Invoke (delegate () {}, delegate {})); Assert (false, e2.Compile ().Invoke (ed, delegate {})); Assert (true, e2.Compile ().Invoke (ed, ed)); */ } void ExclusiveOrTest () { dynamic d = true; var v = false; Assert (d ^ v, true, "#1"); Assert (d ^ true, false, "#1a"); d = 42; var v2 = 62; Assert (d ^ v2, 20, "#2"); Assert (d ^ 0, 42, "#2a"); MyType v3 = new MyType (30); Assert (d ^ v3, new MyType (52), "#3"); dynamic d3 = new MyType (-7); Assert (d3 ^ new MyType (6), new MyType (-1), "#3a"); Assert (d3 ^ 11, -14, "#3b"); } void ExclusiveOrNullableTest () { dynamic d = 5; int? v2 = null; Assert (d ^ v2, null, "#1"); Assert (d ^ null, null, "#1a"); Assert (null ^ d, null, "#1b"); v2 = -2; Assert (d ^ v2, -5, "#2"); dynamic d2 = (int?) -2; Assert (d2 ^ 1, -1, "#2a"); MyType? v3 = new MyType (30); Assert (d ^ v3, new MyType (27), "#3"); dynamic d3 = new MyType? (new MyType (-7)); Assert (d3 ^ new MyType (6), new MyType (-1), "#3a"); Assert (d3 ^ null, null, "#3b"); } void ExclusiveOrTestEnum () { dynamic d = MyEnum.Value_1; Assert (d ^ null, null, "#1"); Assert (d ^ d, 0, "#2"); dynamic d2 = (MyEnumUlong?) MyEnumUlong.Value_1; Assert (d2 ^ MyEnumUlong.Value_2, (MyEnumUlong) 3, "#3"); } void ExclusiveOrAssignedTest () { dynamic d = true; var v = false; d ^= v; Assert (d, true, "#1"); d = true; d ^= true; Assert (d, false, "#1a"); d = 42; var v2 = 62; d ^= v2; Assert (d, 20, "#2"); MyType v3 = new MyType (30); dynamic d3 = new MyType (-7); d3 ^= new MyType (6); Assert (d3, new MyType (-1), "#3"); } void ExclusiveOrAssignedTestEnum () { dynamic d = MyEnum.Value_1; d ^= MyEnum.Value_2; Assert(d, (MyEnum) 3, "#1"); d = MyEnum.Value_2; d ^= d; Assert (d, 0, "#2"); dynamic d2 = (MyEnumUlong?) MyEnumUlong.Value_1; Assert (d2 ^ MyEnumUlong.Value_2, (MyEnumUlong)3, "#3"); } void GreaterThanTest () { dynamic d = 5; int v = 2; Assert (d > v, true, "#1"); double v2 = 5; Assert (d > v2, false, "#1a"); d = 4.6; Assert (d > 4.59, true, "#2"); var b2 = 4.6; Assert (d > b2, false, "#2a"); d = new MyType (30); MyType v3 = new MyType (30); Assert (d > v3, false, "#3"); dynamic d3 = new MyType (-7); Assert (d3 > new MyType (6), false, "#3a"); Assert (d3 > 11, false, "#3b"); d = 2m; decimal v4 = 4m; Assert (d > v4, false, "#4"); Assert (d > 2m, false, "#4a"); } void GreaterThanNullableTest () { dynamic d = 5; int? v2 = null; Assert (d > v2, false, "#1"); Assert (d > null, false, "#1a"); Assert (null > d, false, "#1b"); v2 = -2; Assert (d > v2, true, "#2"); dynamic d2 = (int?) -2; Assert (d2 > 1, false, "#2a"); d2 = (uint?) 44; Assert (d2 > 44, false, "#2b"); d = new MyType (30); MyType? v3 = new MyType (30); Assert (d > v3, false, "#3"); dynamic d3 = new MyType? (new MyType (-7)); Assert (d3 > new MyType (6), false, "#3a"); Assert (d3 > null, false, "#3b"); d = 4.1m; decimal? v4 = 4m; Assert (d > v4, true, "#4"); v4 = null; Assert (d > v4, false, "#4a"); } void GreaterThanEnumTest () { dynamic d = MyEnum.Value_1; Assert (d > null, false, "#1"); Assert (d > MyEnum.Value_1, false, "#2"); Assert (d > 0, true, "#2a"); dynamic d2 = (MyEnumUlong?) MyEnumUlong.Value_2; Assert (d2 > MyEnumUlong.Value_2, false, "#3"); Assert (d2 > null, false, "#3a"); } void GreaterThanEqualTest () { dynamic d = 5; int v = 2; Assert (d >= v, true, "#1"); double v2 = 5; Assert (d >= v2, true, "#1a"); d = 4.6; Assert (d >= 4.59, true, "#2"); var b2 = 4.6; Assert (d >= b2, true, "#2a"); d = new MyType (30); MyType v3 = new MyType (30); Assert (d >= v3, true, "#3"); dynamic d3 = new MyType (-7); Assert (d3 >= new MyType (6), false, "#3a"); Assert (d3 >= 11, false, "#3b"); d = 2m; decimal v4 = 4m; Assert (d >= v4, false, "#4"); Assert (d >= 2m, true, "#4a"); } void GreaterThanEqualNullableTest () { dynamic d = 5; int? v2 = null; Assert (d >= v2, false, "#1"); Assert (d >= null, false, "#1a"); Assert (null >= d, false, "#1b"); v2 = -2; Assert (d >= v2, true, "#2"); dynamic d2 = (int?) -2; Assert (d2 >= 1, false, "#2a"); d2 = (uint?) 44; Assert (d2 >= 44, true, "#2b"); d = new MyType (30); MyType? v3 = new MyType (30); Assert (d >= v3, true, "#3"); dynamic d3 = new MyType? (new MyType (-7)); Assert (d3 >= new MyType (6), false, "#3a"); Assert (d3 >= null, false, "#3b"); d = 4.1m; decimal? v4 = 4m; Assert (d >= v4, true, "#4"); v4 = null; Assert (d >= v4, false, "#4a"); } void GreaterThanEqualEnumTest () { dynamic d = MyEnum.Value_1; Assert (d >= null, false, "#1"); Assert (d >= MyEnum.Value_1, true, "#2"); Assert (d >= 0, true, "#2a"); dynamic d2 = (MyEnumUlong?) MyEnumUlong.Value_2; Assert (d2 >= MyEnumUlong.Value_2, true, "#3"); Assert (d2 >= null, false, "#3a"); } void LeftShiftTest () { dynamic d = (ulong) 0x7F000; int v = 2; Assert (d << v, 0x1FC000, "#1"); Assert (d << 1, 0xFE000, "#1a"); short s = 2; Assert (d << s, 0x1FC000, "#1b"); d = 0x7F000; MyType v3 = new MyType (3); Assert (d << v3, new MyType (0x3F8000), "#3"); dynamic d3 = new MyType (-7); Assert (d3 << new MyType (6), new MyType (-448), "#3a"); Assert (d3 << 11, -14336, "#3b"); } void LeftShiftNullableTest () { dynamic d = 5; int? v2 = null; Assert (d << v2, null, "#1"); d = 5; Assert (d << null, null, "#1a"); d = 5; Assert (null << d, null, "#1b"); v2 = -2; Assert (d << v2, 0x40000000, "#2"); dynamic d2 = (int?) -2; Assert (d2 << 1, -4, "#2a"); d = 0xFFFFFF; MyType? v3 = new MyType (30); Assert (d << v3, new MyType (-1073741824), "#3"); dynamic d3 = new MyType? (new MyType (-7)); Assert (d3 << new MyType (6), new MyType (-448), "#3a"); Assert (d3 << null, null, "#3b"); } void LeftShiftAssignTest () { dynamic d = 0x7F000; int v = 2; d <<= v; Assert (d, 0x1FC000, "#1"); d <<= 1; Assert (d, 0x3F8000, "#1a"); sbyte s = 2; d <<= s; Assert (d, 0xFE0000, "#1b"); } void LeftShiftAssignNullableTest () { dynamic d = 5; var v2 = -2; d <<= v2; Assert (d, 0x40000000, "#2"); dynamic d2 = (int?) -2; d2 <<= 1; Assert (d2, -4, "#2a"); d = 0xFFFFFF; MyType? v3 = new MyType (30); d <<= v3; Assert (d, new MyType (-1073741824), "#3"); dynamic d3 = new MyType? (new MyType (-7)); } void LessThanTest () { dynamic d = 5; int v = 2; Assert (d < v, false, "#1"); double v2 = 5; Assert (d < v2, false, "#1a"); d = 4.6; Assert (d < 4.59, false, "#2"); var b2 = 4.6; Assert (d < b2, false, "#2a"); d = new MyType (30); MyType v3 = new MyType (30); Assert (d < v3, false, "#3"); dynamic d3 = new MyType (-7); Assert (d3 < new MyType (6), true, "#3a"); Assert (d3 < 11, true, "#3b"); d = 2m; decimal v4 = 4m; Assert (d < v4, true, "#4"); Assert (d < 2m, false, "#4a"); } void LessThanNullableTest () { dynamic d = 5; int? v2 = null; Assert (d < v2, false, "#1"); Assert (d < null, false, "#1a"); Assert (null < d, false, "#1b"); v2 = -2; Assert (d < v2, false, "#2"); dynamic d2 = (int?) -2; Assert (d2 < 1, true, "#2a"); d2 = (uint?) 44; Assert (d2 < 44, false, "#2b"); d = new MyType (30); MyType? v3 = new MyType (30); Assert (d < v3, false, "#3"); dynamic d3 = new MyType? (new MyType (-7)); Assert (d3 < new MyType (6), true, "#3a"); Assert (d3 < null, false, "#3b"); d = 4.1m; decimal? v4 = 4m; Assert (d < v4, false, "#4"); v4 = null; Assert (d < v4, false, "#4a"); } void LessThanEnumTest () { dynamic d = MyEnum.Value_1; Assert (d < null, false, "#1"); Assert (d < MyEnum.Value_1, false, "#2"); Assert (d < 0, false, "#2a"); dynamic d2 = (MyEnumUlong?) MyEnumUlong.Value_2; Assert (d2 < MyEnumUlong.Value_2, false, "#3"); Assert (d2 < null, false, "#3a"); } void LessThanOrEqualTest () { dynamic d = 5; int v = 2; Assert (d <= v, false, "#1"); double v2 = 5; Assert (d <= v2, true, "#1a"); d = 4.6; Assert (d <= 4.59, false, "#2"); var b2 = 4.6; Assert (d <= b2, true, "#2a"); d = new MyType (30); MyType v3 = new MyType (30); Assert (d <= v3, true, "#3"); dynamic d3 = new MyType (-7); Assert (d3 <= new MyType (6), true, "#3a"); Assert (d3 <= 11, true, "#3b"); d = 2m; decimal v4 = 4m; Assert (d <= v4, true, "#4"); Assert (d <= 2m, true, "#4a"); } void LessThanOrEqualNullableTest () { dynamic d = 5; int? v2 = null; Assert (d <= v2, false, "#1"); Assert (d <= null, false, "#1a"); Assert (null <= d, false, "#1b"); v2 = -2; Assert (d <= v2, false, "#2"); dynamic d2 = (int?) -2; Assert (d2 <= 1, true, "#2a"); d2 = (uint?) 44; Assert (d2 <= 44, true, "#2b"); d = new MyType (30); MyType? v3 = new MyType (30); Assert (d <= v3, true, "#3"); dynamic d3 = new MyType? (new MyType (-7)); Assert (d3 <= new MyType (6), true, "#3a"); Assert (d3 <= null, false, "#3b"); d = 4.1m; decimal? v4 = 4m; Assert (d <= v4, false, "#4"); v4 = null; Assert (d <= v4, false, "#4a"); } void LessThanOrEqualEnumTest () { dynamic d = MyEnum.Value_1; Assert (d <= null, false, "#1"); Assert (d <= MyEnum.Value_1, true, "#2"); Assert (d <= 0, false, "#2a"); dynamic d2 = (MyEnumUlong?) MyEnumUlong.Value_2; Assert (d2 <= MyEnumUlong.Value_2, true, "#3"); Assert (d2 <= null, false, "#3a"); } void ModuloTest () { dynamic d = 5; int v = 2; Assert (d % v, 1, "#1"); MyType v3 = new MyType (30); Assert (d % v3, new MyType (5), "#3"); dynamic d3 = new MyType (-7); Assert (d3 + new MyType (6), new MyType (-1), "#3a"); Assert (d3 % 11, -7, "#3b"); decimal v4 = 4m; Assert (d % v4, 1m, "#4"); } void ModuloNullableTest () { dynamic d = 5; double? v2 = null; Assert (d % v2, null, "#1"); Assert (d % null, null, "#1a"); Assert (null % d, null, "#1b"); v2 = -2; Assert (d % v2, 1, "#2"); dynamic d2 = (int?) -2; Assert (d2 % 1, 0, "#2a"); MyType? v3 = new MyType (30); Assert (d % v3, new MyType (5), "#3"); dynamic d3 = new MyType? (new MyType (-7)); Assert (d3 % new MyType (6), new MyType (-1), "#3a"); Assert (d3 + null, null, "#3b"); decimal? v4 = 4m; Assert (d % v4, 1m, "#4"); v4 = null; Assert (d % v4, null, "#4a"); } void ModuloAssignTest () { dynamic d = 5; int v = 2; d %= v; Assert (d, 1, "#1"); d = 5.0; double v2 = 0.5; d %= v2; Assert (d, 0, "#1a"); d %= v; Assert (d, 0, "#1b"); dynamic d3 = new MyType (-7); d3 %= new MyType (6); Assert (d3, new MyType (-1), "#3"); d = 5m; decimal v4 = 4m; d %= v4; Assert (d, 1m, "#4"); } void MultiplyTest () { dynamic d = 5; int v = 2; Assert (d * v, 10, "#1"); double v2 = 0.5; Assert (d * v2, 2.5, "#1a"); MyType v3 = new MyType (30); Assert (d * v3, new MyType (150), "#3"); dynamic d3 = new MyType (-7); Assert (d3 * new MyType (6), new MyType (-42), "#3a"); Assert (d3 * 11, -77, "#3b"); decimal v4 = 4m; d = 7.9m; Assert (d * v4, 31.6m, "#4"); } void MultiplyNullableTest () { dynamic d = 5; int? v2 = null; Assert (d * v2, null, "#1"); Assert (d * null, null, "#1a"); Assert (null * d, null, "#1b"); v2 = -2; Assert (d * v2, -10, "#2"); dynamic d2 = (int?) -2; Assert (d2 * 1, -2, "#2a"); MyType? v3 = new MyType (30); Assert (d * v3, new MyType (150), "#3"); dynamic d3 = new MyType? (new MyType (-7)); Assert (d3 * new MyType (6), new MyType (-42), "#3a"); Assert (d3 * null, null, "#3b"); decimal? v4 = 4m; Assert (d * v4, 20m, "#4"); v4 = null; Assert (d * v4, null, "#4a"); } void MultiplyCheckedTest () { checked { dynamic d = 5; int v = int.MaxValue; AssertChecked (() => d * v, 7, "#1"); int? v2 = v; AssertChecked (() => d * v2, null, "#2"); MyType v3 = new MyType (int.MaxValue); AssertChecked (() => d * v3, new MyType (35), "#3"); } } void MultiplyAssignTest () { dynamic d = 5; int v = 2; d *= v; Assert (d, 10, "#1"); d = 5.0; double v2 = 0.5; d *= v2; Assert (d, 2.5, "#1a"); d *= v; Assert (d, 5, "#1b"); dynamic d3 = new MyType (-7); d3 *= new MyType (6); Assert (d3, new MyType (-42), "#3"); d = 5m; decimal v4 = 4m; d *= v4; Assert (d, 20m, "#4"); } void MultiplyAssignCheckedTest () { checked { dynamic d = 5; int v = int.MaxValue; AssertChecked (() => { d *= v; Assert (d, 0, "#1-"); }, "#1"); MyType v3 = new MyType (int.MaxValue); AssertChecked (() => { d *= v3; Assert (d, 0, "#3-"); }, "#3"); } } void NotEqualTest () { dynamic d = 5; int v = 2; Assert (d != v, true, "#1"); double v2 = 5; Assert (d != v2, false, "#1a"); d = true; Assert (d != false, true, "#2"); bool b2 = true; Assert (d != b2, false, "#2a"); d = new MyType (30); MyType v3 = new MyType (30); Assert (d != v3, false, "#3"); dynamic d3 = new MyType (-7); Assert (d3 != new MyType (6), true, "#3a"); Assert (d3 != 11, true, "#3b"); d = 2m; decimal v4 = 4m; Assert (d != v4, true, "#4"); Assert (d != 2m, false, "#4a"); d = null; Assert (d != null, false, "#5"); } void NotEqualNullableTest () { dynamic d = 5; int? v2 = null; Assert (d != v2, true, "#1"); Assert (d != null, true, "#1a"); Assert (null != d, true, "#1b"); v2 = -2; Assert (d != v2, true, "#2"); dynamic d2 = (int?) -2; Assert (d2 != 1, true, "#2a"); d2 = (uint?) 44; Assert (d2 != 44, false, "#2b"); d = new MyType (30); MyType? v3 = new MyType (30); Assert (d != v3, false, "#3"); dynamic d3 = new MyType? (new MyType (-7)); Assert (d3 != new MyType (6), true, "#3a"); Assert (d3 != null, true, "#3b"); d = 4.1m; decimal? v4 = 4m; Assert (d != v4, true, "#4"); v4 = null; Assert (d != v4, true, "#4a"); d = (bool?) true; Assert (d != true, false, "#5"); Assert (d != null, true, "#5a"); Assert (d != false, true, "#5b"); } void NotEqualEnumTest () { dynamic d = MyEnum.Value_1; Assert (d != null, true, "#1"); Assert (d != MyEnum.Value_1, false, "#2"); Assert (d != 0, true, "#2a"); dynamic d2 = (MyEnumUlong?) MyEnumUlong.Value_2; Assert (d2 != MyEnumUlong.Value_2, false, "#3"); Assert (d2 != null, true, "#3a"); } void NotEqualStringTest () { dynamic d = "text"; Assert (d != "te", true, "#1"); Assert (d != "text", false, "#1a"); Assert (d != null, true, "#1b"); } void OrTest () { dynamic d = true; var v = false; Assert (d | v, true, "#1"); Assert (d | false, true, "#1a"); d = 42; var v2 = 62; Assert (d | v2, 62, "#2"); Assert (d | 0, 42, "#2a"); MyType v3 = new MyType (30); Assert (d | v3, new MyType (62), "#3"); dynamic d3 = new MyType (-7); Assert (d3 | new MyType (6), new MyType (-1), "#3a"); Assert (d3 | 11, -5, "#3b"); } void OrTestEnum () { dynamic d = MyEnum.Value_1; Assert (d | null, null, "#1"); Assert (d | d, MyEnum.Value_1, "#2"); dynamic d2 = (MyEnumUlong?) MyEnumUlong.Value_1; Assert (d2 | MyEnumUlong.Value_2, (MyEnumUlong) 3, "#3"); } void OrTestNullable () { dynamic d = 5; int? v2 = null; Assert (d | v2, null, "#1"); Assert (d | null, null, "#1a"); Assert (null | d, null, "#1b"); v2 = -2; Assert (d | v2, -1, "#2"); dynamic d2 = (int?) -2; Assert (d2 | 1, -1, "#2a"); MyType? v3 = new MyType (30); Assert (d | v3, new MyType (31), "#3"); dynamic d3 = new MyType? (new MyType (-7)); Assert (d3 | new MyType (6), new MyType (-1), "#3a"); Assert (d3 + null, null, "#3b"); } void OrAssignedTest () { dynamic d = true; var v = false; d |= v; Assert (d, true, "#1"); d = true; d |= true; Assert (d, true, "#1a"); d = 42; var v2 = 62; d |= v2; Assert (d, 62, "#2"); MyType v3 = new MyType (30); dynamic d3 = new MyType (-7); d3 |= new MyType (6); Assert (d3, new MyType (-1), "#3"); } void OrAssignedTestEnum () { dynamic d = MyEnum.Value_1; d |= MyEnum.Value_2; Assert (d, (MyEnum) 3, "#1"); d = MyEnum.Value_2; d |= d; Assert (d, MyEnum.Value_2, "#2"); dynamic d2 = (MyEnumUlong?) MyEnumUlong.Value_1; Assert (d2 | MyEnumUlong.Value_2, (MyEnumUlong)3, "#3"); } void OrElseTest () { dynamic d = true; var v = false; Assert (d || v, true, "#1"); Assert (d || true, true, "#1a"); d = true; Assert (d || d, true, "#2"); dynamic d3 = new MyType (-7); Assert (d3 || new MyType (6), new MyType (-7), "#3"); Assert (d3 || 11, -7, "#3b"); } void RightShiftTest () { dynamic d = (ulong) 0x7F000; int v = 2; Assert (d >> v, 0x1FC00, "#1"); Assert (d >> 1, 0x3F800, "#1a"); short s = 2; Assert (d >> s, 0x1FC00, "#1b"); d = 0x7F000; MyType v3 = new MyType (3); Assert (d >> v3, new MyType (0xFE00), "#3"); dynamic d3 = new MyType (-7); Assert (d3 >> new MyType (6), new MyType (-1), "#3a"); Assert (d3 >> 11, -1, "#3b"); } void RightShiftNullableTest () { dynamic d = 5; int? v2 = null; Assert (d >> v2, null, "#1"); d = 5; Assert (d >> null, null, "#1a"); d = 5; Assert (null >> d, null, "#1b"); v2 = -2; Assert (d >> v2, 0, "#2"); dynamic d2 = (int?) -200; Assert (d2 >> 1, -100, "#2a"); d = 0xFFFFFF; MyType? v3 = new MyType (3); Assert (d >> v3, new MyType (0x1FFFFF), "#3"); dynamic d3 = new MyType? (new MyType (-7)); Assert (d3 >> new MyType (6), new MyType (-1), "#3a"); Assert (d3 >> null, null, "#3b"); } void RightShiftAssignTest () { dynamic d = 0x7F000; int v = 2; d >>= v; Assert (d, 0x1FC00, "#1"); d >>= 1; Assert (d, 0xFE00, "#1a"); sbyte s = 2; d >>= s; Assert (d, 0x3F80, "#1b"); } void RightShiftAssignNullableTest () { dynamic d = 0x2A0; var v2 = -2; d >>= v2; Assert (d, 0, "#2"); dynamic d2 = (int?) -2; d2 >>= 1; Assert (d2, -1, "#2a"); d = 0xFFFFFF; MyType? v3 = new MyType (3); d >>= v3; Assert (d, new MyType (0x1FFFFF), "#3"); } void SubtractTest () { dynamic d = 5; int v = 2; Assert (d - v, 3, "#1"); double v2 = 0.5; Assert (d - v2, 4.5, "#1a"); MyType v3 = new MyType (30); Assert (d - v3, new MyType (-25), "#3"); dynamic d3 = new MyType (-7); Assert (d3 - new MyType (6), new MyType (-13), "#3a"); Assert (d3 - 11, -18, "#3b"); decimal v4 = 4m; Assert (d - v4, 1m, "#4"); } void SubtractNullableTest () { dynamic d = 5; int? v2 = null; Assert (d - v2, null, "#1"); Assert (d - null, null, "#1a"); Assert (null - d, null, "#1b"); v2 = -2; Assert (d - v2, 7, "#2"); dynamic d2 = (int?) -2; Assert (d2 - 1, -3, "#2a"); MyType? v3 = new MyType (30); Assert (d - v3, new MyType (-25), "#3"); dynamic d3 = new MyType? (new MyType (-7)); Assert (d3 - new MyType (6), new MyType (-13), "#3a"); Assert (d3 - null, null, "#3b"); decimal? v4 = 4m; Assert (d - v4, 1m, "#4"); v4 = null; Assert (d - v4, null, "#4a"); } void SubtractEnumTest () { dynamic d = MyEnum.Value_1; // CSC: Invalid System.InvalidOperationException Assert (d - null, null, "#1"); Assert (d - 1, MyEnum.Value_2, "#2"); dynamic d2 = (MyEnumUlong?) MyEnumUlong.Value_1; Assert (d2 - (byte) 1, MyEnumUlong.Value_2, "#3"); Assert (d2 - (object) null, null, "#3a"); } void SubtractCheckedTest () { checked { dynamic d = 5; int v = int.MinValue; AssertChecked (() => d - v, 7, "#1"); int? v2 = v; AssertChecked (() => d - v2, null, "#2"); MyType v3 = new MyType (int.MinValue); AssertChecked (() => d - v3, new MyType (35), "#3"); } } void SubtractAssignTest () { dynamic d = 5; int v = 2; d -= v; Assert (d, 3, "#1"); d = 5.0; double v2 = 0.5; d -= v2; Assert (d, 4.5, "#1a"); d -= v; Assert (d, 2.5, "#1b"); dynamic d3 = new MyType (-7); d3 -= new MyType (6); Assert (d3, new MyType (-13), "#3"); d = 5m; decimal v4 = 4m; d -= v4; Assert (d, 1m, "#4"); } void SubtractAssignEnumTest () { dynamic d = MyEnum.Value_1; d -= 1; Assert (d, 0, "#2"); dynamic d2 = (MyEnumUlong?) MyEnumUlong.Value_2; d2 -= (byte) 1; Assert (d2, MyEnumUlong.Value_1, "#3"); } void SubtractAssignCheckedTest () { checked { dynamic d = 5; int v = int.MinValue; AssertChecked (() => { d -= v; Assert (d, 0, "#1a"); }, "#1"); MyType v3 = new MyType (int.MinValue); AssertChecked (() => { d -= v3; Assert (d, 0, "#3a"); }, "#3"); } } // TODO: void SubtractAssignmentEvent () { // IMPLEMENT } #pragma warning restore 169 static bool RunTest (MethodInfo test) { Console.Write ("Running test {0, -25}", test.Name); try { test.Invoke (new Tester (), null); Console.WriteLine ("OK"); return true; } catch (Exception e) { Console.WriteLine ("FAILED"); Console.WriteLine (e.InnerException.Message); return false; } } public static int Main () { var tests = from test in typeof (Tester).GetMethods (BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly) where test.GetParameters ().Length == 0 orderby test.Name select RunTest (test); int failures = tests.Count (a => !a); Console.WriteLine (failures + " tests failed"); return failures; } }