Skip to content

Commit 8c649fd

Browse files
authored
Fix some race condition issue (#1477)
1 parent f0b2b7d commit 8c649fd

File tree

1 file changed

+17
-9
lines changed

1 file changed

+17
-9
lines changed

src/Adapter/MSTest.TestAdapter/Execution/UnitTestRunner.cs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

44
using System;
5+
using System.Collections.Concurrent;
56
using System.Collections.Generic;
67
using System.Diagnostics.CodeAnalysis;
78
using System.Globalization;
@@ -288,33 +289,40 @@ private class ClassCleanupManager
288289
private readonly ClassCleanupBehavior? _lifecycleFromMsTest;
289290
private readonly ClassCleanupBehavior _lifecycleFromAssembly;
290291
private readonly ReflectHelper _reflectHelper;
291-
private readonly Dictionary<string, HashSet<string>> _remainingTestsByClass;
292+
private readonly ConcurrentDictionary<string, HashSet<string>> _remainingTestsByClass;
292293

293294
public ClassCleanupManager(
294295
IEnumerable<UnitTestElement> testsToRun,
295296
ClassCleanupBehavior? lifecycleFromMsTest,
296297
ClassCleanupBehavior lifecycleFromAssembly,
297298
ReflectHelper? reflectHelper = null)
298299
{
299-
_remainingTestsByClass = testsToRun.GroupBy(t => t.TestMethod.FullClassName)
300-
.ToDictionary(
301-
g => g.Key,
302-
g => new HashSet<string>(g.Select(t => t.TestMethod.UniqueName)));
300+
_remainingTestsByClass =
301+
new(testsToRun.GroupBy(t => t.TestMethod.FullClassName)
302+
.ToDictionary(
303+
g => g.Key,
304+
g => new HashSet<string>(g.Select(t => t.TestMethod.UniqueName))));
303305
_lifecycleFromMsTest = lifecycleFromMsTest;
304306
_lifecycleFromAssembly = lifecycleFromAssembly;
305307
_reflectHelper = reflectHelper ?? new ReflectHelper();
306308
}
307309

308-
public void MarkTestComplete(TestMethodInfo testMethodInfo, TestMethod testMethod, out bool shouldRunEndOfClassCleanup, out bool shouldRunEndOfAssemblyCleanup)
310+
public void MarkTestComplete(TestMethodInfo testMethodInfo, TestMethod testMethod, out bool shouldRunEndOfClassCleanup,
311+
out bool shouldRunEndOfAssemblyCleanup)
309312
{
310313
shouldRunEndOfClassCleanup = false;
311-
var testsByClass = _remainingTestsByClass[testMethodInfo.TestClassName];
314+
shouldRunEndOfAssemblyCleanup = false;
315+
if (!_remainingTestsByClass.TryGetValue(testMethodInfo.TestClassName, out var testsByClass))
316+
{
317+
return;
318+
}
319+
312320
lock (testsByClass)
313321
{
314322
testsByClass.Remove(testMethod.UniqueName);
315323
if (testsByClass.Count == 0)
316324
{
317-
_remainingTestsByClass.Remove(testMethodInfo.TestClassName);
325+
_remainingTestsByClass.TryRemove(testMethodInfo.TestClassName, out _);
318326
if (testMethodInfo.Parent.HasExecutableCleanupMethod)
319327
{
320328
var cleanupLifecycle = _reflectHelper.GetClassCleanupBehavior(testMethodInfo.Parent)
@@ -325,7 +333,7 @@ public void MarkTestComplete(TestMethodInfo testMethodInfo, TestMethod testMetho
325333
}
326334
}
327335

328-
shouldRunEndOfAssemblyCleanup = _remainingTestsByClass.Count == 0;
336+
shouldRunEndOfAssemblyCleanup = _remainingTestsByClass.IsEmpty;
329337
}
330338
}
331339
}

0 commit comments

Comments
 (0)