From 7c671355610ee6e10358ace094b325df7997dee0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 24 Apr 2026 09:10:46 +0000 Subject: [PATCH 1/2] Initial plan From de5ae31efeeb0689acf99acaed3b5d649a2a90d0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 24 Apr 2026 09:22:54 +0000 Subject: [PATCH 2/2] Fix O(n) linear scan in TestNodeUidListFilter by using HashSet for O(1) membership test Agent-Logs-Url: https://github.com/microsoft/testfx/sessions/fa2343e0-6020-4160-8937-17fa45259f87 Co-authored-by: Evangelink <11340282+Evangelink@users.noreply.github.com> --- .../TestingFramework/TestingFramework.cs | 11 ++++++----- .../MSTest.Engine/Engine/BFSTestNodeVisitor.cs | 11 +++++++++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/samples/public/TestingPlatformExamples/TestingPlatformExplorer/TestingFramework/TestingFramework.cs b/samples/public/TestingPlatformExamples/TestingPlatformExplorer/TestingFramework/TestingFramework.cs index 40712fee8d..e7c7091043 100644 --- a/samples/public/TestingPlatformExamples/TestingPlatformExplorer/TestingFramework/TestingFramework.cs +++ b/samples/public/TestingPlatformExamples/TestingPlatformExplorer/TestingFramework/TestingFramework.cs @@ -142,15 +142,16 @@ public async Task ExecuteRequestAsync(ExecuteRequestContext context) StringBuilder reportBody = new(); MethodInfo[] tests = GetTestsMethodFromAssemblies(); + HashSet? uidFilterSet = runTestExecutionRequest.Filter is TestNodeUidListFilter filter + ? [.. filter.TestNodeUids] + : null; var results = new List(); foreach (MethodInfo test in tests) { - if (runTestExecutionRequest.Filter is TestNodeUidListFilter filter) + if (uidFilterSet is not null + && !uidFilterSet.Contains($"{test.DeclaringType!.FullName}.{test.Name}")) { - if (!filter.TestNodeUids.Any(testId => testId == $"{test.DeclaringType!.FullName}.{test.Name}")) - { - continue; - } + continue; } SkipAttribute? skipAttribute = test.GetCustomAttribute(); diff --git a/src/Adapter/MSTest.Engine/Engine/BFSTestNodeVisitor.cs b/src/Adapter/MSTest.Engine/Engine/BFSTestNodeVisitor.cs index faa7301a1b..cdf5a26bb1 100644 --- a/src/Adapter/MSTest.Engine/Engine/BFSTestNodeVisitor.cs +++ b/src/Adapter/MSTest.Engine/Engine/BFSTestNodeVisitor.cs @@ -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 @@ -32,6 +34,11 @@ public BFSTestNodeVisitor(IEnumerable rootTestNodes, ITestExecutionFil public async Task VisitAsync(Func onIncludedTestNodeAsync) { + // Precompute a HashSet for O(1) UID lookups when filtering by UID list. + HashSet? 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> testNodesByUid = []; Queue<(TestNode CurrentNode, TestNodeUid? ParentNodeUid, StringBuilder NodeFullPath)> queue = new(); @@ -81,8 +88,8 @@ public async Task VisitAsync(Func 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())) { await onIncludedTestNodeAsync(currentNode, parentNodeUid).ConfigureAwait(false); }