Skip to content

Commit

Permalink
Bump xunit from 2.9.0 to 2.9.2 (#1037)
Browse files Browse the repository at this point in the history
* Bump xunit from 2.9.0 to 2.9.2

Bumps [xunit](https://github.com/xunit/xunit) from 2.9.0 to 2.9.2.
- [Commits](xunit/xunit@2.9.0...2.9.2)

---
updated-dependencies:
- dependency-name: xunit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>

* Update attribute to handle Xunit 2.9.2

* Formatting pls

* Exclude from code coverage

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Isaac Daly <[email protected]>
  • Loading branch information
dependabot[bot] and dalyIsaac authored Sep 28, 2024
1 parent a4f3ea4 commit 6b195f7
Show file tree
Hide file tree
Showing 2 changed files with 186 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageVersion Include="NSubstitute" Version="5.1.0" />
<PackageVersion Include="NSubstitute.Analyzers.CSharp" Version="1.0.17" />
<PackageVersion Include="xunit" Version="2.9.0" />
<PackageVersion Include="xunit" Version="2.9.2" />
<PackageVersion Include="xunit.analyzers" Version="1.16.0" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
</ItemGroup>
Expand Down
185 changes: 185 additions & 0 deletions src/Whim.TestUtils/MemberAutoSubstituteDataAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Reflection;
using AutoFixture;
Expand All @@ -13,6 +17,7 @@ namespace Whim.TestUtils;
/// Creates an AutoFixture fixture with NSubstitute support and injects the given arguments, to be
/// used like <c>MemberData</c> for an xunit <c>Theory</c>.
/// </summary>
[ExcludeFromCodeCoverage]
public abstract class BaseMemberAutoSubstituteDataAttribute : MemberDataAttributeBase
{
/// <summary>
Expand All @@ -28,6 +33,69 @@ public abstract class BaseMemberAutoSubstituteDataAttribute : MemberDataAttribut
internal BaseMemberAutoSubstituteDataAttribute(string memberName, params object[] parameters)
: base(memberName, parameters) { }

/// <inheritdoc/>
public override IEnumerable<object[]>? GetData(MethodInfo testMethod)
{
ArgumentNullException.ThrowIfNull(testMethod);

Type? type =
(MemberType ?? testMethod.DeclaringType)
?? throw new ArgumentException(
string.Format(
CultureInfo.CurrentCulture,
"Could not determine member type for member '{0}'",
MemberName
)
);

Func<object?> accessor =
(GetPropertyAccessor(type) ?? GetFieldAccessor(type) ?? GetMethodAccessor(type))
?? throw new ArgumentException(
string.Format(
CultureInfo.CurrentCulture,
"Could not find public static member (property, field, or method) named '{0}' on {1}{2}",
MemberName,
type.FullName,
Parameters?.Length > 0
? string.Format(
CultureInfo.CurrentCulture,
" with parameter types: {0}",
string.Join(", ", Parameters.Select(p => p?.GetType().FullName ?? "(null)"))
)
: ""
)
);

object? obj = accessor();
IEnumerable<object[]>? accessedEnumerable = null;

if (obj == null)
{
return null;
}
else if (obj is IEnumerable<object[]> arrayEnumerable)
{
accessedEnumerable = arrayEnumerable;
}
else if (obj is IEnumerable enumerable)
{
accessedEnumerable = (IEnumerable<object[]>?)enumerable.Cast<object>();
}
else
{
throw new ArgumentException(
string.Format(
CultureInfo.CurrentCulture,
"Property {0} on {1} did not return IEnumerable",
MemberName,
type.FullName
)
);
}

return accessedEnumerable?.Select(item => ConvertDataItem(testMethod, item));
}

/// <inheritdoc/>
protected override object[] ConvertDataItem(MethodInfo testMethod, object item)
{
Expand Down Expand Up @@ -62,6 +130,123 @@ private static object GetSpecimen(IFixture fixture, ParameterInfo parameter)

return new SpecimenContext(fixture).Resolve(parameter);
}

// Copied from https://github.com/xunit/xunit/blob/82543a6df6f5f13b5b70f8a9f9ccb41cd676084f/src/xunit.core/MemberDataAttributeBase.cs
private Func<object?>? GetFieldAccessor(Type type)
{
FieldInfo? fieldInfo = null;
for (
Type? reflectionType = type;
reflectionType != null;
reflectionType = reflectionType.GetTypeInfo().BaseType
)
{
fieldInfo = reflectionType.GetRuntimeField(MemberName);
if (fieldInfo != null)
{
break;
}
}

if (fieldInfo == null || !fieldInfo.IsStatic)
{
return null;
}

return () => fieldInfo.GetValue(null);
}

private Func<object?>? GetMethodAccessor(Type type)
{
MethodInfo? methodInfo = null;
Type?[] parameterTypes = Parameters == null ? [] : Parameters.Select(p => p?.GetType()).ToArray();
for (
Type? reflectionType = type;
reflectionType != null;
reflectionType = reflectionType.GetTypeInfo().BaseType
)
{
MethodInfo[] runtimeMethodsWithGivenName = reflectionType
.GetRuntimeMethods()
.Where(m => m.Name == MemberName)
.ToArray();
methodInfo = runtimeMethodsWithGivenName.FirstOrDefault(m =>
ParameterTypesCompatible(m.GetParameters(), parameterTypes)
);

if (methodInfo != null)
{
break;
}

if (runtimeMethodsWithGivenName.Any(m => m.GetParameters().Any(p => p.IsOptional)))
{
throw new ArgumentException(
string.Format(
CultureInfo.CurrentCulture,
"Method '{0}.{1}' contains optional parameters, which are not currently supported. Please use overloads if necessary.",
type.FullName,
MemberName
)
);
}
}

if (methodInfo == null || !methodInfo.IsStatic)
{
return null;
}

return () => methodInfo.Invoke(null, Parameters);
}

private Func<object?>? GetPropertyAccessor(Type type)
{
PropertyInfo? propInfo = null;
for (
Type? reflectionType = type;
reflectionType != null;
reflectionType = reflectionType.GetTypeInfo().BaseType
)
{
propInfo = reflectionType.GetRuntimeProperty(MemberName);
if (propInfo != null)
{
break;
}
}

if (propInfo == null || propInfo.GetMethod == null || !propInfo.GetMethod.IsStatic)
{
return null;
}

return () => propInfo.GetValue(null, null);
}

private static bool ParameterTypesCompatible(ParameterInfo[] parameters, Type?[] parameterTypes)
{
if (parameters?.Length != parameterTypes.Length)
{
return false;
}

for (int idx = 0; idx < parameters.Length; ++idx)
{
Type? currentType = parameterTypes[idx];

if (
currentType != null
&& parameterTypes[idx] != null
&& !parameters[idx].ParameterType.GetTypeInfo().IsAssignableFrom(currentType.GetTypeInfo())
)
{
return false;
}
}

return true;
}
}

/// <summary>
Expand Down

0 comments on commit 6b195f7

Please sign in to comment.