Fixing bug with strict enum flags parsing not correctly handling composite values

This commit is contained in:
Chris Cameron
2017-09-11 10:09:51 -04:00
parent b48525949e
commit c3451d62b0
2 changed files with 58 additions and 35 deletions

View File

@@ -71,6 +71,9 @@ namespace ICD.Common.Utils.Tests
{ {
Assert.IsFalse(EnumUtils.IsDefined((eTestEnum)20)); Assert.IsFalse(EnumUtils.IsDefined((eTestEnum)20));
Assert.IsTrue(EnumUtils.IsDefined((eTestEnum)2)); Assert.IsTrue(EnumUtils.IsDefined((eTestEnum)2));
Assert.IsFalse(EnumUtils.IsDefined((eTestFlagsEnum)8));
Assert.IsTrue(EnumUtils.IsDefined((eTestFlagsEnum)3));
} }
#region Values #region Values
@@ -262,18 +265,29 @@ namespace ICD.Common.Utils.Tests
{ {
Assert.AreEqual(eTestEnum.A, EnumUtils.ParseStrict<eTestEnum>("1", false)); Assert.AreEqual(eTestEnum.A, EnumUtils.ParseStrict<eTestEnum>("1", false));
Assert.Throws<ArgumentOutOfRangeException>(() => EnumUtils.ParseStrict<eTestEnum>("4", false)); Assert.Throws<ArgumentOutOfRangeException>(() => EnumUtils.ParseStrict<eTestEnum>("4", false));
Assert.AreEqual(eTestFlagsEnum.A | eTestFlagsEnum.B, EnumUtils.ParseStrict<eTestFlagsEnum>("3", false));
Assert.Throws<ArgumentOutOfRangeException>(() => EnumUtils.ParseStrict<eTestFlagsEnum>("8", false));
} }
[Test] [Test]
public void TryParseStrictGenericTest() public void TryParseStrictGenericTest()
{ {
eTestEnum output; eTestEnum outputA;
Assert.AreEqual(true, EnumUtils.TryParseStrict("1", false, out output)); Assert.AreEqual(true, EnumUtils.TryParseStrict("1", false, out outputA));
Assert.AreEqual(eTestEnum.A, output); Assert.AreEqual(eTestEnum.A, outputA);
Assert.AreEqual(false, EnumUtils.TryParseStrict("4", false, out output)); Assert.AreEqual(false, EnumUtils.TryParseStrict("4", false, out outputA));
Assert.AreEqual(eTestEnum.None, output); Assert.AreEqual(eTestEnum.None, outputA);
eTestFlagsEnum outputB;
Assert.AreEqual(true, EnumUtils.TryParseStrict("3", false, out outputB));
Assert.AreEqual(eTestFlagsEnum.A | eTestFlagsEnum.B, outputB);
Assert.AreEqual(false, EnumUtils.TryParseStrict("8", false, out outputB));
Assert.AreEqual(eTestFlagsEnum.None, outputB);
} }
[Test] [Test]

View File

@@ -63,7 +63,19 @@ namespace ICD.Common.Utils
if (!IsEnumType(typeof(T))) if (!IsEnumType(typeof(T)))
throw new InvalidOperationException(string.Format("{0} is not an enum", typeof(T).Name)); throw new InvalidOperationException(string.Format("{0} is not an enum", typeof(T).Name));
if (!IsFlagsEnum<T>())
return GetValues<T>().Any(v => v.Equals(value)); return GetValues<T>().Any(v => v.Equals(value));
int valueInt = (int)GetUnderlyingValue(value);
// Check if all of the flag values are defined
foreach (T flag in GetFlags(value))
{
int flagInt = (int)GetUnderlyingValue(flag);
valueInt = valueInt - flagInt;
}
return valueInt == 0;
} }
#region Values #region Values
@@ -396,15 +408,12 @@ namespace ICD.Common.Utils
if (!IsEnumType<T>()) if (!IsEnumType<T>())
throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name)); throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name));
try T output;
{ if (TryParse(data, ignoreCase, out output))
return (T)Enum.Parse(typeof(T), data, ignoreCase); return output;
}
catch (Exception e) string message = string.Format("Failed to parse {0} as {1}", StringUtils.ToRepresentation(data), typeof(T).Name);
{ throw new FormatException(message);
throw new FormatException(
string.Format("Failed to parse {0} as {1}", StringUtils.ToRepresentation(data), typeof(T).Name), e);
}
} }
/// <summary> /// <summary>
@@ -424,7 +433,7 @@ namespace ICD.Common.Utils
try try
{ {
result = Parse<T>(data, ignoreCase); result = (T)Enum.Parse(typeof(T), data, ignoreCase);
return true; return true;
} }
catch (Exception) catch (Exception)