Skip to content

Commit e2c61c2

Browse files
committed
xunit/xunit#3075: Attempt to resolve dictionary throwing for duplicate key
1 parent 5f8a322 commit e2c61c2

File tree

2 files changed

+15
-14
lines changed

2 files changed

+15
-14
lines changed

src/xunit.runner.visualstudio/Sinks/VsExecutionSink.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,14 @@ internal sealed class VsExecutionSink : TestMessageSink, IDisposable
3434
readonly ConcurrentDictionary<string, List<ITestCaseStarting>> testCasesByClassID = [];
3535
readonly ConcurrentDictionary<string, List<ITestCaseStarting>> testCasesByCollectionID = [];
3636
readonly ConcurrentDictionary<string, List<ITestCaseStarting>> testCasesByMethodID = [];
37-
readonly Dictionary<string, VsTestCase> testCasesMap;
37+
readonly IReadOnlyDictionary<string, VsTestCase> testCasesMap;
3838
static readonly Uri uri = new(Constants.ExecutorUri);
3939

4040
public VsExecutionSink(
4141
IMessageSink innerSink,
4242
VsTestExecutionRecorder recorder,
4343
LoggerHelper logger,
44-
Dictionary<string, VsTestCase> testCasesMap,
44+
IReadOnlyDictionary<string, VsTestCase> testCasesMap,
4545
Func<bool> cancelledThunk)
4646
{
4747
this.innerSink = innerSink;

src/xunit.runner.visualstudio/VsTestRunner.cs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Concurrent;
23
using System.Collections.Generic;
34
using System.ComponentModel;
45
using System.Diagnostics;
@@ -514,8 +515,8 @@ async Task RunTestsInAssembly(
514515
if (controller is null)
515516
return;
516517

517-
var testCasesMap = new Dictionary<string, TestCase>();
518-
var testCaseSerializations = new List<string>();
518+
var testCasesMap = new ConcurrentDictionary<string, TestCase>();
519+
var testCaseSerializations = new ConcurrentBag<string>();
519520
if (runInfo.TestCases is null || runInfo.TestCases.Count == 0)
520521
{
521522
// Discover tests
@@ -553,14 +554,14 @@ await DiscoverTestsInAssembly(
553554
foreach (var filteredTestCase in filteredTestCases)
554555
{
555556
var uniqueID = filteredTestCase.UniqueID;
556-
if (testCasesMap.ContainsKey(uniqueID))
557-
logger.LogWarningWithSource(assemblyFileName, "Skipping test case with duplicate ID '{0}' ('{1}' and '{2}')", uniqueID, testCasesMap[uniqueID].DisplayName, filteredTestCase.VSTestCase?.DisplayName);
558-
else if (string.IsNullOrEmpty(filteredTestCase.TestCase.Serialization))
557+
if (string.IsNullOrEmpty(filteredTestCase.TestCase.Serialization))
559558
logger.LogWarningWithSource(assemblyFileName, "Skipping test case '{0}' (ID '{1}') without serialization", filteredTestCase.TestCase.TestCaseDisplayName, filteredTestCase.TestCase.TestCaseUniqueID);
560559
else if (filteredTestCase.VSTestCase is not null)
561560
{
562-
testCasesMap.Add(uniqueID, filteredTestCase.VSTestCase);
563-
testCaseSerializations.Add(filteredTestCase.TestCase.Serialization);
561+
if (testCasesMap.TryAdd(uniqueID, filteredTestCase.VSTestCase))
562+
testCaseSerializations.Add(filteredTestCase.TestCase.Serialization);
563+
else
564+
logger.LogWarningWithSource(assemblyFileName, "Skipping test case with duplicate ID '{0}' ('{1}' and '{2}')", uniqueID, testCasesMap[uniqueID].DisplayName, filteredTestCase.VSTestCase?.DisplayName);
564565
}
565566
}
566567
}
@@ -576,20 +577,20 @@ await DiscoverTestsInAssembly(
576577

577578
if (uniqueID is null)
578579
logger.LogWarningWithSource(assemblyFileName, "VSTestCase {0} did not have an associated unique ID", testCase.DisplayName);
579-
else if (testCasesMap.ContainsKey(uniqueID))
580-
logger.LogWarningWithSource(assemblyFileName, "Skipping test case with duplicate ID '{0}' ('{1}' and '{2}')", uniqueID, testCasesMap[uniqueID].DisplayName, testCase.DisplayName);
581580
else if (string.IsNullOrEmpty(serialization))
582581
logger.LogWarningWithSource(assemblyFileName, "Skipping test case '{0}' (ID '{1}') without serialization", testCase.DisplayName, uniqueID);
583582
else
584583
{
585-
testCasesMap[uniqueID] = testCase;
586-
testCaseSerializations.Add(serialization);
584+
if (testCasesMap.TryAdd(uniqueID, testCase))
585+
testCaseSerializations.Add(serialization);
586+
else
587+
logger.LogWarningWithSource(assemblyFileName, "Skipping test case with duplicate ID '{0}' ('{1}' and '{2}')", uniqueID, testCasesMap[uniqueID].DisplayName, testCase.DisplayName);
587588
}
588589
}
589590
}
590591

591592
// https://github.com/xunit/visualstudio.xunit/issues/417
592-
if (testCaseSerializations.Count == 0)
593+
if (testCaseSerializations.IsEmpty)
593594
{
594595
if (configuration.InternalDiagnosticMessagesOrDefault)
595596
logger.LogWarning("Skipping '{0}': no tests passed the filter", assemblyFileName);

0 commit comments

Comments
 (0)