Skip to content

Commit

Permalink
xunit/xunit#2767: Special case FileSystemInfo objects by just compari…
Browse files Browse the repository at this point in the history
…ng the FullName in Assert.Equivalent
  • Loading branch information
bradwilson committed Sep 1, 2023
1 parent 78d70de commit 482be8e
Showing 1 changed file with 38 additions and 0 deletions.
38 changes: 38 additions & 0 deletions Sdk/AssertHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#else
// In case this is source-imported with global nullable enabled but no XUNIT_NULLABLE
#pragma warning disable CS8600
#pragma warning disable CS8601
#pragma warning disable CS8603
#pragma warning disable CS8604
#pragma warning disable CS8621
Expand Down Expand Up @@ -44,6 +45,14 @@ internal static class AssertHelper
static ConcurrentDictionary<Type, Dictionary<string, Func<object, object>>> gettersByType = new ConcurrentDictionary<Type, Dictionary<string, Func<object, object>>>();
#endif

#if XUNIT_NULLABLE
static readonly TypeInfo? fileSystemInfoTypeInfo = Type.GetType("System.IO.FileSystemInfo")?.GetTypeInfo();
static readonly PropertyInfo? fileSystemInfoFullNameProperty = fileSystemInfoTypeInfo?.GetDeclaredProperty("FullName");
#else
static readonly TypeInfo fileSystemInfoTypeInfo = Type.GetType("System.IO.FileSystemInfo")?.GetTypeInfo();
static readonly PropertyInfo fileSystemInfoFullNameProperty = fileSystemInfoTypeInfo?.GetDeclaredProperty("FullName");
#endif

#if XUNIT_NULLABLE
static Dictionary<string, Func<object?, object?>> GetGettersForType(Type type) =>
#else
Expand Down Expand Up @@ -234,6 +243,8 @@ internal static string ShortenAndEncodeStringEnd(string value)
{
var expectedType = expected.GetType();
var expectedTypeInfo = expectedType.GetTypeInfo();
var actualType = actual.GetType();
var actualTypeInfo = actualType.GetTypeInfo();

// Primitive types, enums and strings should just fall back to their Equals implementation
if (expectedTypeInfo.IsPrimitive || expectedTypeInfo.IsEnum || expectedType == typeof(string))
Expand All @@ -244,6 +255,11 @@ internal static string ShortenAndEncodeStringEnd(string value)
if (expectedType == typeof(DateTime) || expectedType == typeof(DateTimeOffset))
return VerifyEquivalenceDateTime(expected, actual, prefix);

// FileSystemInfo has a recursion problem when getting the root directory
if (fileSystemInfoTypeInfo != null)
if (fileSystemInfoTypeInfo.IsAssignableFrom(expectedTypeInfo) && fileSystemInfoTypeInfo.IsAssignableFrom(actualTypeInfo))
return VerifyEquivalenceFileSystemInfo(expected, actual, strict, prefix, expectedRefs, actualRefs, depth);

// Enumerables? Check equivalence of individual members
var enumerableExpected = expected as IEnumerable;
var enumerableActual = actual as IEnumerable;
Expand Down Expand Up @@ -341,6 +357,28 @@ internal static string ShortenAndEncodeStringEnd(string value)
return null;
}

#if XUNIT_NULLABLE
static EquivalentException? VerifyEquivalenceFileSystemInfo(
#else
static EquivalentException VerifyEquivalenceFileSystemInfo(
#endif
object expected,
object actual,
bool strict,
string prefix,
HashSet<object> expectedRefs,
HashSet<object> actualRefs,
int depth)
{
if (fileSystemInfoFullNameProperty == null)
throw new InvalidOperationException("Could not find 'FullName' property on type 'System.IO.FileSystemInfo'");

var fullName = fileSystemInfoFullNameProperty.GetValue(expected);
var expectedAnonymous = new { FullName = fullName };

return VerifyEquivalenceReference(expectedAnonymous, actual, strict, prefix, expectedRefs, actualRefs, depth);
}

#if XUNIT_NULLABLE
static EquivalentException? VerifyEquivalenceIntrinsics(
#else
Expand Down

0 comments on commit 482be8e

Please sign in to comment.