// EnumTest.cs - NUnit Test Cases for the System.Enum class // // David Brandt (bucky@keystreams.com) // // (C) Ximian, Inc. http://www.ximian.com // using NUnit.Framework; using System; using System.IO; using System.Reflection; namespace MonoTests.System { public class EnumTest : TestCase { public EnumTest() {} protected override void SetUp() { } protected override void TearDown() { } enum TestingEnum {This, Is, A, Test}; enum TestingEnum2 {This, Is, A, Test}; enum TestingEnum3: ulong {This, Is, A, Test = ulong.MaxValue }; public void TestCompareTo() { Enum e1 = new TestingEnum(); Enum e2 = new TestingEnum(); Enum e3 = new TestingEnum2(); AssertEquals("An enum should equal itself", 0, e1.CompareTo(e1)); AssertEquals("An enum should equal a copy", 0, e1.CompareTo(e2)); TestingEnum x = TestingEnum.This; TestingEnum y = TestingEnum.Is; AssertEquals("should equal", 0, x.CompareTo(x)); AssertEquals("less than", -1, x.CompareTo(y)); AssertEquals("greater than", 1, y.CompareTo(x)); { bool errorThrown = false; try { e1.CompareTo(e3); } catch (ArgumentException) { errorThrown = true; } Assert("1) Compare type mismatch not caught.", errorThrown); } { bool errorThrown = false; try { ((Enum)e1).CompareTo((Enum)e3); } catch (ArgumentException) { errorThrown = true; } Assert("2) Compare type mismatch not caught.", errorThrown); } } public void TestEquals() { Enum e1 = new TestingEnum(); Enum e2 = new TestingEnum(); Enum e3 = new TestingEnum2(); Assert("An enum should equal itself", e1.Equals(e1)); Assert("An enum should equal a copy", e1.Equals(e2)); Assert("Shouldn't match", !e1.Equals(e3)); Assert("Shouldn't match null", !e1.Equals(null)); } public void TestFormat_Args() { try { TestingEnum x = TestingEnum.Test; Enum.Format(null, x, "G"); Fail("null first arg not caught."); } catch (ArgumentNullException) { // do nothing } catch (Exception e) { Fail("first arg null, wrong exception: " + e.ToString()); } try { Enum.Format(typeof(TestingEnum), null, "G"); Fail("null second arg not caught."); } catch (ArgumentNullException) { // do nothing } catch (Exception e) { Fail("second arg null, wrong exception: " + e.ToString()); } try { TestingEnum x = TestingEnum.Test; Enum.Format(x.GetType(), x, null); Fail("null third arg not caught."); } catch (ArgumentNullException) { // do nothing } catch (Exception e) { Fail("third arg null, wrong exception: " + e.ToString()); } try { TestingEnum x = TestingEnum.Test; Enum.Format(typeof(string), x, "G"); Fail("bad type arg not caught."); } catch (ArgumentException) { // do nothing } catch (Exception e) { Fail("bad type, wrong exception: " + e.ToString()); } try { TestingEnum x = TestingEnum.Test; TestingEnum2 y = TestingEnum2.Test; Enum.Format(y.GetType(), x, "G"); Fail("wrong enum type not caught."); } catch (ArgumentException) { // do nothing } catch (Exception e) { Fail("wrong enum type, wrong exception: " + e.ToString()); } try { String bad = "huh?"; TestingEnum x = TestingEnum.Test; Enum.Format(x.GetType(), bad, "G"); Fail("non-enum object not caught."); } catch (ArgumentException) { // do nothing } catch (Exception e) { Fail("non-enum object, wrong exception: " + e.ToString()); } string[] codes = {"a", "b", "c", "ad", "e", "af", "ag", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "ax", "y", "z"}; foreach (string code in codes) { try { TestingEnum x = TestingEnum.Test; Enum.Format(x.GetType(), x, code); Fail ("bad format code not caught - " + code); } catch (FormatException) { // do nothing } catch (Exception e) { Fail (String.Format ("bad format code ({0}), wrong exception: {1}", code, e.ToString())); } } TestingEnum ex = TestingEnum.Test; AssertEquals("decimal format wrong", "3", Enum.Format(ex.GetType(), ex, "d")); AssertEquals("decimal format wrong for ulong enums", "18446744073709551615", Enum.Format(typeof(TestingEnum3), TestingEnum3.Test, "d")); AssertEquals("named format wrong", "Test", Enum.Format(ex.GetType(), ex, "g")); AssertEquals("hex format wrong", "00000003", Enum.Format(ex.GetType(), ex, "x")); AssertEquals("bitfield format wrong", "Test", Enum.Format(ex.GetType(), ex, "f")); } public void TestFormat_FormatSpecifier () { ParameterAttributes pa = ParameterAttributes.In | ParameterAttributes.HasDefault; const string fFormatOutput = "In, HasDefault"; const string xFormatOutput = "00001001"; string fOutput = Enum.Format (pa.GetType(), pa, "f"); AssertEquals ("#F_FS:f", fFormatOutput, fOutput); string xOutput = Enum.Format (pa.GetType(), pa, "x"); AssertEquals ("#F_FS:x", xFormatOutput, xOutput); } public void TestGetHashCode() { Enum e1 = new TestingEnum(); Enum e2 = new TestingEnum2(); AssertEquals("hash code is deterministic", e1.GetHashCode(), e1.GetHashCode()); } public void GetName() { { bool errorThrown = false; try { TestingEnum x = TestingEnum.Test; Enum.GetName(null, x); } catch (ArgumentNullException) { errorThrown = true; } Assert("null first arg not caught.", errorThrown); } { bool errorThrown = false; try { TestingEnum x = TestingEnum.Test; Enum.GetName(x.GetType(), null); } catch (ArgumentNullException) { errorThrown = true; } Assert("null second arg not caught.", errorThrown); } { bool errorThrown = false; try { String bad = "huh?"; TestingEnum x = TestingEnum.Test; Enum.GetName(bad.GetType(), x); } catch (ArgumentException) { errorThrown = true; } Assert("non-enum type not caught.", errorThrown); } { bool errorThrown = false; try { TestingEnum x = TestingEnum.Test; TestingEnum2 y = TestingEnum2.Test; Enum.GetName(y.GetType(), x); } catch (ArgumentException) { errorThrown = true; } Assert("wrong enum type not caught.", errorThrown); } { bool errorThrown = false; try { String bad = "huh?"; TestingEnum x = TestingEnum.Test; Enum.GetName(x.GetType(), bad); } catch (ArgumentException) { errorThrown = true; } Assert("non-enum object not caught.", errorThrown); } { TestingEnum x = TestingEnum.This; TestingEnum y = TestingEnum.Is; TestingEnum z = TestingEnum.A; AssertEquals("first name doesn't match", "This", Enum.GetName(x.GetType(), x)); AssertEquals("second name doesn't match", "Is", Enum.GetName(y.GetType(), y)); AssertEquals("third name doesn't match", "A", Enum.GetName(z.GetType(), z)); } } public void TestGetNames() { { bool errorThrown = false; try { Enum.GetNames(null); } catch (ArgumentNullException) { errorThrown = true; } Assert("null type not caught.", errorThrown); } { TestingEnum x = TestingEnum.This; string[] match = {"This", "Is", "A", "Test"}; string[] names = Enum.GetNames(x.GetType()); AssertNotNull("Got no names", names); AssertEquals("names wrong size", match.Length, names.Length); for (int i = 0; i < names.Length; i++) { AssertEquals("name mismatch", match[i], names[i]); } } } public void TestGetTypeCode() { TestingEnum x = TestingEnum.This; TestingEnum y = new TestingEnum(); AssertEquals("01 bad type code", TypeCode.Int32, x.GetTypeCode()); AssertEquals("02 bad type code", TypeCode.Int32, y.GetTypeCode()); } enum TestShortEnum : short { zero, one, two, three, four, five, six}; public void TestGetUnderlyingType() { { bool errorThrown = false; try { Enum.GetUnderlyingType(null); } catch (ArgumentNullException) { errorThrown = true; } Assert("null type not caught.", errorThrown); } { bool errorThrown = false; try { String bad = "huh?"; Enum.GetUnderlyingType(bad.GetType()); } catch (ArgumentException) { errorThrown = true; } Assert("non-enum type not caught.", errorThrown); } { short sh = 5; int i = 5; Enum t1 = new TestingEnum(); Enum t2 = new TestShortEnum(); AssertEquals("Wrong default underlying type", i.GetType(), Enum.GetUnderlyingType(t1.GetType())); AssertEquals("Not short underlying type", sh.GetType(), Enum.GetUnderlyingType(t2.GetType())); } } public void TestGetValues() { { bool errorThrown = false; try { Enum.GetValues(null); } catch (ArgumentNullException) { errorThrown = true; } Assert("null type not caught.", errorThrown); } { bool errorThrown = false; try { String bad = "huh?"; Enum.GetValues(bad.GetType()); } catch (ArgumentException) { errorThrown = true; } Assert("non-enum type not caught.", errorThrown); } { Enum t1 = new TestingEnum(); Array a1 = Enum.GetValues(t1.GetType()); for (int i= 0; i < a1.Length; i++) { AssertEquals("wrong enum value", (TestingEnum)i, a1.GetValue(i)); } } { Enum t1 = new TestShortEnum(); Array a1 = Enum.GetValues(t1.GetType()); for (short i= 0; i < a1.Length; i++) { AssertEquals("wrong short enum value", (TestShortEnum)i, a1.GetValue(i)); } } } public void TestIsDefined() { { bool errorThrown = false; try { Enum.IsDefined(null, 1); } catch (ArgumentNullException) { errorThrown = true; } Assert("null first arg not caught.", errorThrown); } { bool errorThrown = false; try { TestingEnum x = TestingEnum.Test; Enum.IsDefined(x.GetType(), null); } catch (ArgumentNullException) { errorThrown = true; } Assert("null second arg not caught.", errorThrown); } { bool errorThrown = false; try { String bad = "huh?"; int i = 4; Enum.IsDefined(bad.GetType(), i); } catch (ArgumentException) { errorThrown = true; } Assert("non-enum type not caught.", errorThrown); } try { TestingEnum x = TestingEnum.Test; short i = 4; Enum.IsDefined(x.GetType(), i); Fail("wrong underlying type not caught."); } catch (ArgumentException) { } catch (Exception e) { Fail("wrong Exception thrown ("+e.ToString()+")for underlying type not caught."); } // spec says yes, MS impl says no. //{ //bool errorThrown = false; //try { //String bad = "huh?"; //TestingEnum x = TestingEnum.Test; //Enum.IsDefined(x.GetType(), bad); //} catch (ExecutionEngineException) { //errorThrown = true; //} //Assert("non-enum object not caught.", //errorThrown); //} { Enum t1 = new TestingEnum(); int i = 0; for (i = 0; i < Enum.GetValues(t1.GetType()).Length; i++) { Assert("should have value for i=" + i, Enum.IsDefined(t1.GetType(), i)); } Assert("Shouldn't have value", !Enum.IsDefined(t1.GetType(), i)); } } public void TestParse1() { { bool errorThrown = false; try { String name = "huh?"; Enum.Parse(null, name); } catch (ArgumentNullException) { errorThrown = true; } Assert("null first arg not caught.", errorThrown); } { bool errorThrown = false; try { TestingEnum x = TestingEnum.Test; Enum.Parse(x.GetType(), null); } catch (ArgumentNullException) { errorThrown = true; } Assert("null second arg not caught.", errorThrown); } { bool errorThrown = false; try { String bad = "huh?"; Enum.Parse(bad.GetType(), bad); } catch (ArgumentException) { errorThrown = true; } Assert("non-enum type not caught.", errorThrown); } { bool errorThrown = false; try { TestingEnum x = TestingEnum.Test; String bad = ""; Enum.Parse(x.GetType(), bad); } catch (ArgumentException) { errorThrown = true; } Assert("empty string not caught.", errorThrown); } { bool errorThrown = false; try { TestingEnum x = TestingEnum.Test; String bad = " "; Enum.Parse(x.GetType(), bad); } catch (ArgumentException) { errorThrown = true; } Assert("space-only string not caught.", errorThrown); } { bool errorThrown = false; try { String bad = "huh?"; TestingEnum x = TestingEnum.Test; Enum.Parse(x.GetType(), bad); } catch (ArgumentException) { errorThrown = true; } Assert("not-in-enum error not caught.", errorThrown); } { TestingEnum t1 = new TestingEnum(); AssertEquals("parse first enum", TestingEnum.This, Enum.Parse(t1.GetType(), "This")); AssertEquals("parse second enum", TestingEnum.Is, Enum.Parse(t1.GetType(), "Is")); AssertEquals("parse third enum", TestingEnum.A, Enum.Parse(t1.GetType(), "A")); AssertEquals("parse last enum", TestingEnum.Test, Enum.Parse(t1.GetType(), "Test")); AssertEquals("parse last enum with whitespace", TestingEnum.Test, Enum.Parse(t1.GetType(), " \n\nTest\t")); AssertEquals("parse bitwise-or enum", TestingEnum.Is, Enum.Parse(t1.GetType(), "This,Is")); AssertEquals("parse bitwise-or enum", TestingEnum.Test, Enum.Parse(t1.GetType(), "This,Test")); AssertEquals("parse bitwise-or enum", TestingEnum.Test, Enum.Parse(t1.GetType(), "This,Is,A")); AssertEquals("parse bitwise-or enum with whitespace", TestingEnum.Test, Enum.Parse(t1.GetType(), " \n\tThis \t\n, Is,A \n")); } } public void TestParse2() { { bool errorThrown = true; try { String name = "huh?"; Enum.Parse(null, name, true); } catch (ArgumentNullException) { errorThrown = true; } Assert("null first arg not caught.", errorThrown); } { bool errorThrown = true; try { TestingEnum x = TestingEnum.Test; Enum.Parse(x.GetType(), null, true); } catch (ArgumentNullException) { errorThrown = true; } Assert("null second arg not caught.", errorThrown); } { bool errorThrown = true; try { String bad = "huh?"; Enum.Parse(bad.GetType(), bad, true); } catch (ArgumentException) { errorThrown = true; } Assert("non-enum type not caught.", errorThrown); } { bool errorThrown = true; try { TestingEnum x = TestingEnum.Test; String bad = ""; Enum.Parse(x.GetType(), bad, true); } catch (ArgumentException) { errorThrown = true; } Assert("empty string not caught.", errorThrown); } { bool errorThrown = true; try { TestingEnum x = TestingEnum.Test; String bad = " "; Enum.Parse(x.GetType(), bad, true); } catch (ArgumentException) { errorThrown = true; } Assert("space-only string not caught.", errorThrown); } { bool errorThrown = true; try { String bad = "huh?"; TestingEnum x = TestingEnum.Test; Enum.Parse(x.GetType(), bad, true); } catch (ArgumentException) { errorThrown = true; } Assert("not-in-enum error not caught.", errorThrown); } { bool errorThrown = true; try { String bad = "test"; TestingEnum x = TestingEnum.Test; Enum.Parse(x.GetType(), bad, false); } catch (ArgumentException) { errorThrown = true; } Assert("not-in-enum error not caught.", errorThrown); } { TestingEnum t1 = new TestingEnum(); AssertEquals("parse first enum", TestingEnum.This, Enum.Parse(t1.GetType(), "this", true)); AssertEquals("parse second enum", TestingEnum.Is, Enum.Parse(t1.GetType(), "is", true)); AssertEquals("parse third enum", TestingEnum.A, Enum.Parse(t1.GetType(), "a", true)); AssertEquals("parse last enum", TestingEnum.Test, Enum.Parse(t1.GetType(), "test", true)); AssertEquals("parse last enum with whitespace", TestingEnum.Test, Enum.Parse(t1.GetType(), " \n\ntest\t", true)); AssertEquals("parse bitwise-or enum", TestingEnum.Is, Enum.Parse(t1.GetType(), "This,is", true)); AssertEquals("parse bitwise-or enum", TestingEnum.Test, Enum.Parse(t1.GetType(), "This,test", true)); AssertEquals("parse bitwise-or enum", TestingEnum.Test, Enum.Parse(t1.GetType(), "This,is,A", true)); AssertEquals("parse bitwise-or enum with whitespace", TestingEnum.Test, Enum.Parse(t1.GetType(), " \n\tThis \t\n, is,a \n", true)); } } [Test] public void ParseValue() { TestingEnum3 t1 = new TestingEnum3(); AssertEquals ("Parse numeric value", TestingEnum3.Test, Enum.Parse(t1.GetType(), "18446744073709551615", false)); } public void TestToObject() { { bool errorThrown = false; try { Enum.ToObject(null, 1); } catch (ArgumentNullException) { errorThrown = true; } Assert("null type not caught.", errorThrown); } { bool errorThrown = false; try { Enum.ToObject("huh?".GetType(), 1); } catch (ArgumentException) { errorThrown = true; } Assert("null type not caught.", errorThrown); } { TestingEnum t1 = new TestingEnum(); AssertEquals("Should get object", TestingEnum.This, Enum.ToObject(t1.GetType(), 0)); } // TODO - should probably test all the different underlying types } [Flags] enum SomeEnum {a,b,c}; [Flags] enum SomeByteEnum : byte {a,b,c}; [Flags] enum SomeInt64Enum : long {a,b,c}; public void TestToString() { int i = 0; try { i++; AssertEquals("invalid string", "This", TestingEnum.This.ToString()); i++; AssertEquals("invalid string", "Is", TestingEnum.Is.ToString()); i++; AssertEquals("invalid string", "A", TestingEnum.A.ToString()); i++; AssertEquals("invalid string", "Test", TestingEnum.Test.ToString()); Enum is1 = TestingEnum.Is; i++; AssertEquals("decimal parse wrong", "1", is1.ToString("d")); i++; AssertEquals("named format wrong", "Is", is1.ToString("g")); i++; AssertEquals("hex format wrong", "00000001", is1.ToString("x")); i++; AssertEquals("bitfield format wrong", "Is", is1.ToString("f")); i++; AssertEquals("bitfield with flags format wrong for Int32 enum", "b, c", ((SomeEnum)3).ToString("f")); i++; AssertEquals("bitfield with flags format wrong for Byte enum", "b, c", ((SomeByteEnum)3).ToString("f")); i++; AssertEquals("bitfield with flags format wrong for Int64 enum", "b, c", ((SomeInt64Enum)3).ToString("f")); i++; AssertEquals("bitfield with unknown flags format wrong for Int32 enum", "12", ((SomeEnum)12).ToString("f")); i++; AssertEquals("bitfield with unknown flags format wrong for Byte enum", "12", ((SomeByteEnum)12).ToString("f")); i++; AssertEquals("bitfield with unknown flags format wrong for Int64 enum", "12", ((SomeInt64Enum)12).ToString("f")); } catch (Exception e) { Fail ("Unexpected exception at i = " + i + " with e=" + e); } } enum E { Aa=0, Bb=1, Cc=2, Dd=3, } [Flags] enum E2 { Aa, Bb, Cc, Dd, } [Test] public void FlagTest () { int [] evalues = new int [4] {0,1,2,3}; E [] e = new E [4] {E.Aa, E.Bb, E.Cc, E.Dd}; for (int i = 0; i < 4; ++i) { Assertion.AssertEquals ("#" + i, e [i].ToString (), Enum.Format (typeof (E), evalues [i], "f")); } } [Test] public void FlagTest2 () { int invalidValue = 1000; Assertion.AssertEquals ("#01", invalidValue.ToString (), Enum.Format (typeof (E2), invalidValue, "g")); } enum E3 {A=0,B=1,C=2,D=3,} enum UE : ulong {A=1,B=2,C=4,D=8,} enum EA {A=0, B=2, C=3, D=4} [Test] public void AnotherFormatBugPinned () { Assertion.AssertEquals ("#01", "100", Enum.Format (typeof (E3), 100, "f")); } [Test] public void LogicBugPinned () { string format=null; string[] names=new string[] {"A","B","C","D",}; string[] fmtSpl=null; UE ue = UE.A | UE.B | UE.C | UE.D; //all flags must be in format return format = Enum.Format (typeof (UE), ue, "f"); fmtSpl = format.Split (','); for( int i=0 ; i= 0); foreach (string nval in names) Assertion.Assert (nval + " is not contained in format return.", Array.IndexOf (fmtSpl, nval) >= 0); } // TODO - ToString with IFormatProviders } }