Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -142,15 +142,16 @@ public async Task ExecuteRequestAsync(ExecuteRequestContext context)

StringBuilder reportBody = new();
MethodInfo[] tests = GetTestsMethodFromAssemblies();
HashSet<TestNodeUid>? uidFilterSet = runTestExecutionRequest.Filter is TestNodeUidListFilter filter
? [.. filter.TestNodeUids]
: null;
var results = new List<Task>();
foreach (MethodInfo test in tests)
{
if (runTestExecutionRequest.Filter is TestNodeUidListFilter filter)
if (uidFilterSet is not null
&& !uidFilterSet.Contains($"{test.DeclaringType!.FullName}.{test.Name}"))
{
Comment on lines +151 to 153
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this sample, uidFilterSet is a HashSet<TestNodeUid> but Contains is called with an interpolated string, which relies on the implicit string -> TestNodeUid conversion and allocates a new TestNodeUid per check. If you want this to be allocation-free, consider storing uid.Value in a HashSet<string> (e.g., with StringComparer.Ordinal) and comparing against the computed UID string.

Copilot uses AI. Check for mistakes.
if (!filter.TestNodeUids.Any(testId => testId == $"{test.DeclaringType!.FullName}.{test.Name}"))
{
continue;
}
continue;
}

SkipAttribute? skipAttribute = test.GetCustomAttribute<SkipAttribute>();
Expand Down
11 changes: 9 additions & 2 deletions src/Adapter/MSTest.Engine/Engine/BFSTestNodeVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
using Microsoft.Testing.Platform.Extensions.Messages;
using Microsoft.Testing.Platform.Requests;

using PlatformTestNodeUid = Microsoft.Testing.Platform.Extensions.Messages.TestNodeUid;

namespace Microsoft.Testing.Framework;

internal sealed class BFSTestNodeVisitor
Expand All @@ -32,6 +34,11 @@ public BFSTestNodeVisitor(IEnumerable<TestNode> rootTestNodes, ITestExecutionFil

public async Task VisitAsync(Func<TestNode, TestNodeUid?, Task> onIncludedTestNodeAsync)
{
// Precompute a HashSet for O(1) UID lookups when filtering by UID list.
HashSet<PlatformTestNodeUid>? uidFilterSet = _testExecutionFilter is TestNodeUidListFilter listFilter
? [.. listFilter.TestNodeUids]
: null;

// This is case sensitive, and culture insensitive, to keep UIDs unique, and comparable between different system.
Dictionary<TestNodeUid, List<TestNode>> testNodesByUid = [];
Queue<(TestNode CurrentNode, TestNodeUid? ParentNodeUid, StringBuilder NodeFullPath)> queue = new();
Expand Down Expand Up @@ -81,8 +88,8 @@ public async Task VisitAsync(Func<TestNode, TestNodeUid?, Task> onIncludedTestNo
}

// If the node is not filtered out by the test execution filter, we call the callback with the node.
if (_testExecutionFilter is not TestNodeUidListFilter listFilter
|| listFilter.TestNodeUids.Any(uid => currentNode.StableUid.ToPlatformTestNodeUid() == uid))
if (uidFilterSet is null
|| uidFilterSet.Contains(currentNode.StableUid.ToPlatformTestNodeUid()))
Comment on lines +91 to +92
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

currentNode.StableUid is already Microsoft.Testing.Platform.Extensions.Messages.TestNodeUid, so calling ToPlatformTestNodeUid() here allocates a new TestNodeUid per visited node. If you want this to be allocation-free (and likely drop the PlatformTestNodeUid alias), you can check uidFilterSet.Contains(currentNode.StableUid) directly.

Copilot uses AI. Check for mistakes.
{
await onIncludedTestNodeAsync(currentNode, parentNodeUid).ConfigureAwait(false);
}
Expand Down