Skip to content

Commit

Permalink
Fixed bugs in ManagedMethod parsing, and updated hierarchies.
Browse files Browse the repository at this point in the history
  • Loading branch information
Haplois committed Jun 1, 2022
1 parent 557359e commit af50d49
Show file tree
Hide file tree
Showing 23 changed files with 367 additions and 112 deletions.
5 changes: 5 additions & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@ PublicAPI.Unshipped.txt @nohwnd @MarcoRossignoli
# something that should be treated with care and we should be transparent about it. It also
# requires making sure all telemetry collection systems in place will continue to function well.
TelemetryDataConstants.cs @cvpoienaru @nohwnd

# Changes here might break our contracts with other adapters, and possibly
# Visual Studio.
/src/Microsoft.TestPlatform.AdapterUtilities/ @haplois @Evangelink
/test/Microsoft.TestPlatform.AdapterUtilities.UnitTests/ @haplois @Evangelink
32 changes: 29 additions & 3 deletions src/Microsoft.TestPlatform.AdapterUtilities/HierarchyConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,42 @@ public static class Levels
/// <summary>
/// Total length of Hierarchy array.
/// </summary>
public const int TotalLevelCount = 2;
/// <remarks>
/// Currently the order for this is usually:
/// <c>Managed Method Name</c>, <c>ClassName</c>, <c>Namespace</c>, <c>Assembly Display Name</c>.
/// </remarks>
public const int TotalLevelCount = 4;

/// <summary>
/// Index of the namespace element of the array.
/// Index of the test group element of the array.
/// </summary>
public const int NamespaceIndex = 0;
/// <remarks>
/// This is usually test method name.
/// </remarks>
public const int TestGroupIndex = 0;

/// <summary>
/// Index of the class element of the array.
/// </summary>
/// <remarks>
/// This is usually test class name without namespace.
/// </remarks>
public const int ClassIndex = 1;

/// <summary>
/// Index of the namespace element of the array.
/// </summary>
/// <remarks>
/// This is usually test namespace without class name.
/// </remarks>
public const int NamespaceIndex = 2;

/// <summary>
/// Index of the test container element of the array.
/// </summary>
/// <remarks>
/// This is usually test asssembly display name.
/// </remarks>
public const int ContainerIndex = 3;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,7 @@ public static void GetManagedName(MethodBase method, out string managedTypeName,

if (!ReflectionHelpers.IsMethod(method))
{
// TODO: @Haplois, exception expects a message and not a param name.
throw new NotSupportedException(nameof(method));
throw new ArgumentException(Resources.Resources.ErrorMethodExpectedAsAnArgument, nameof(method));
}

var semanticType = ReflectionHelpers.GetReflectedType(method)
Expand Down Expand Up @@ -119,11 +118,11 @@ public static void GetManagedName(MethodBase method, out string managedTypeName,
var methodBuilder = new StringBuilder();

// Namespace and Type Name (with arity designation)
// hierarchyPos contains [startIndexOfNamespace, endIndexOfNameSpace, endIndexOfTypeName]
var hierarchyPos = AppendTypeString(typeBuilder, semanticType, closedType: false);
if (hierarchyPos is null || hierarchyPos.Length != HierarchyConstants.Levels.TotalLevelCount)
if (hierarchyPos is null || hierarchyPos.Length != 3)
{
// TODO: @Haplois, exception expects a message and not a param name.
throw new NotSupportedException(nameof(method));
throw new ArgumentException(Resources.Resources.ErrorMethodExpectedAsAnArgument, nameof(method));
}

// Method Name with method arity
Expand All @@ -134,6 +133,7 @@ public static void GetManagedName(MethodBase method, out string managedTypeName,
methodBuilder.Append('`');
methodBuilder.Append(arity);
}
var methodNameEndIndex = methodBuilder.Length;

// Type Parameters
var paramList = method.GetParameters();
Expand All @@ -151,11 +151,12 @@ public static void GetManagedName(MethodBase method, out string managedTypeName,

managedTypeName = typeBuilder.ToString();
managedMethodName = methodBuilder.ToString();
hierarchyValues = new[]
{
managedTypeName.Substring(hierarchyPos[0], hierarchyPos[1] - hierarchyPos[0]),
managedTypeName.Substring(hierarchyPos[1] + 1, hierarchyPos[2] - hierarchyPos[1] - 1),
};

hierarchyValues = new string[HierarchyConstants.Levels.TotalLevelCount];
hierarchyValues[HierarchyConstants.Levels.TestGroupIndex] = managedMethodName.Substring(0, methodNameEndIndex);
hierarchyValues[HierarchyConstants.Levels.ClassIndex] = managedTypeName.Substring(hierarchyPos[1] + 1, hierarchyPos[2] - hierarchyPos[1] - 1);
hierarchyValues[HierarchyConstants.Levels.NamespaceIndex] = managedTypeName.Substring(hierarchyPos[0], hierarchyPos[1] - hierarchyPos[0]);
hierarchyValues[HierarchyConstants.Levels.ContainerIndex] = method.DeclaringType.GetTypeInfo().Assembly.GetName().Name;
}

/// <summary>
Expand Down Expand Up @@ -265,7 +266,12 @@ bool Filter(MemberInfo mbr, object? param)
methods = type.GetRuntimeMethods().Where(m => Filter(m, null)).ToArray();
#endif

return (MethodInfo?)methods.SingleOrDefault();
return (MethodInfo?)(methods.Length switch
{
1 => methods[0],
> 1 => methods.SingleOrDefault(i => i.DeclaringType == type),
_ => null
});
}

private static int[]? AppendTypeString(StringBuilder b, Type? type, bool closedType)
Expand Down Expand Up @@ -478,15 +484,33 @@ private static void AppendGenericTypeParameters(StringBuilder b, Type type)

private static bool IsNormalized(string s)
{
var brackets = 0;

for (int i = 0; i < s.Length; i++)
{
if (NeedsEscaping(s[i], i) && s[i] != '.')
var c = s[i];
if (NeedsEscaping(c, i) && c != '.')
{
if (i != 0)
{
if (c == '<')
{
brackets++;
continue;
}

if (c == '>' && s[i - 1] != '<' && brackets > 0)
{
brackets--;
continue;
}
}

return false;
}
}

return true;
return brackets == 0;
}

private static bool NeedsEscaping(char c, int pos)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@

<ItemGroup>
<EmbeddedResource Include="Resources\Resources.resx" />
<!-- Disabled auto code generation to support net20

<Compile Update="Resources\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
Expand All @@ -64,7 +64,6 @@
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
-->
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#nullable enable
const Microsoft.TestPlatform.AdapterUtilities.HierarchyConstants.HierarchyLabel = "Hierarchy" -> string!
const Microsoft.TestPlatform.AdapterUtilities.HierarchyConstants.HierarchyPropertyId = "TestCase.Hierarchy" -> string!
const Microsoft.TestPlatform.AdapterUtilities.HierarchyConstants.Levels.TestGroupIndex = 0 -> int
const Microsoft.TestPlatform.AdapterUtilities.HierarchyConstants.Levels.ClassIndex = 1 -> int
const Microsoft.TestPlatform.AdapterUtilities.HierarchyConstants.Levels.NamespaceIndex = 0 -> int
const Microsoft.TestPlatform.AdapterUtilities.HierarchyConstants.Levels.TotalLevelCount = 2 -> int
const Microsoft.TestPlatform.AdapterUtilities.HierarchyConstants.Levels.NamespaceIndex = 2 -> int
const Microsoft.TestPlatform.AdapterUtilities.HierarchyConstants.Levels.ContainerIndex = 3 -> int
const Microsoft.TestPlatform.AdapterUtilities.HierarchyConstants.Levels.TotalLevelCount = 4 -> int
const Microsoft.TestPlatform.AdapterUtilities.ManagedNameConstants.ManagedMethodLabel = "ManagedMethod" -> string!
const Microsoft.TestPlatform.AdapterUtilities.ManagedNameConstants.ManagedMethodPropertyId = "TestCase.ManagedMethod" -> string!
const Microsoft.TestPlatform.AdapterUtilities.ManagedNameConstants.ManagedTypeLabel = "ManagedType" -> string!
Expand All @@ -18,6 +20,7 @@ Microsoft.TestPlatform.AdapterUtilities.ManagedNameUtilities.ManagedNameParser
Microsoft.TestPlatform.AdapterUtilities.ManagedNameUtilities.ManagedNameParser.ManagedNameParser() -> void
Microsoft.TestPlatform.AdapterUtilities.TestIdProvider
Microsoft.TestPlatform.AdapterUtilities.TestIdProvider.AppendString(string! str) -> void
Microsoft.TestPlatform.AdapterUtilities.TestIdProvider.AppendBytes(byte[]! bytes) -> void
Microsoft.TestPlatform.AdapterUtilities.TestIdProvider.GetHash() -> byte[]!
Microsoft.TestPlatform.AdapterUtilities.TestIdProvider.GetId() -> System.Guid
Microsoft.TestPlatform.AdapterUtilities.TestIdProvider.TestIdProvider() -> void
Expand Down
Loading

0 comments on commit af50d49

Please sign in to comment.