Skip to content

Commit f55dc39

Browse files
authored
Merge settings safely (#771)
1 parent 7f89665 commit f55dc39

File tree

5 files changed

+179
-1
lines changed

5 files changed

+179
-1
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
namespace Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.Helpers
5+
{
6+
using System;
7+
using System.Collections.Generic;
8+
using System.Linq;
9+
10+
internal static class DictionaryHelper
11+
{
12+
public static IDictionary<TKey, TValue> ConcatWithOverwrites<TKey, TValue>(
13+
this IDictionary<TKey, TValue> source,
14+
IDictionary<TKey, TValue> overwrite,
15+
string sourceFriendlyName = "source",
16+
string overwriteFriendlyName = "overwrite")
17+
where TKey : IEquatable<TKey>
18+
{
19+
if ((source == null || source?.Count == 0) && (overwrite == null || overwrite?.Count == 0))
20+
{
21+
PlatformServiceProvider.Instance.AdapterTraceLogger.LogInfo("DictionaryHelper.ConcatWithOverwrites: Both {0} and {1} dictionaries are null or empty, returning empty dictionary.", sourceFriendlyName, overwriteFriendlyName);
22+
return new Dictionary<TKey, TValue>();
23+
}
24+
25+
if (overwrite == null || overwrite?.Count == 0)
26+
{
27+
PlatformServiceProvider.Instance.AdapterTraceLogger.LogInfo("DictionaryHelper.ConcatWithOverwrites: The {0} is null or empty, returning the {1} dictionary.", overwriteFriendlyName, sourceFriendlyName);
28+
return source.ToDictionary(p => p.Key, p => p.Value);
29+
}
30+
31+
if (source == null || source?.Count == 0)
32+
{
33+
PlatformServiceProvider.Instance.AdapterTraceLogger.LogInfo("DictionaryHelper.ConcatWithOverwrites: The {0} is null or empty, returning the {1} dictionary.", sourceFriendlyName, overwriteFriendlyName);
34+
return overwrite.ToDictionary(p => p.Key, p => p.Value);
35+
}
36+
37+
PlatformServiceProvider.Instance.AdapterTraceLogger.LogInfo("DictionaryHelper.ConcatWithOverwrites: The {0} has {1} keys. And {2} has {3} keys. Merging them.", sourceFriendlyName, source.Count, overwriteFriendlyName, overwrite.Count);
38+
var destination = source.ToDictionary(p => p.Key, p => p.Value);
39+
PlatformServiceProvider.Instance.AdapterTraceLogger.LogInfo("DictionaryHelper.ConcatWithOverwrites: Taking all keys from {0}: {1}.", sourceFriendlyName, string.Join(", ", source.Keys));
40+
var overwrites = new List<TKey>();
41+
foreach (var k in overwrite.Keys)
42+
{
43+
if (destination.ContainsKey(k))
44+
{
45+
PlatformServiceProvider.Instance.AdapterTraceLogger.LogInfo("DictionaryHelper.ConcatWithOverwrites: The {0} already contains key {1}. Overwriting it with value from {2}.", sourceFriendlyName, k, overwriteFriendlyName);
46+
destination[k] = overwrite[k];
47+
overwrites.Add(k);
48+
}
49+
else
50+
{
51+
PlatformServiceProvider.Instance.AdapterTraceLogger.LogInfo("DictionaryHelper.ConcatWithOverwrites: The {0} does not contain key {1}. Adding it from {2}.", sourceFriendlyName, k, overwriteFriendlyName);
52+
destination.Add(k, overwrite[k]);
53+
}
54+
}
55+
56+
PlatformServiceProvider.Instance.AdapterTraceLogger.LogInfo("DictionaryHelper.ConcatWithOverwrites: Merging done: Resulting dictionary has keys {0}, overwrites {1}.", string.Join(", ", destination.Keys), string.Join(", ", overwrites));
57+
58+
return destination;
59+
}
60+
}
61+
}

src/Adapter/MSTest.CoreAdapter/MSTest.CoreAdapter.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
<Compile Include="Extensions\TestContextExtensions.cs" />
3939
<Compile Include="Extensions\TestResultExtensions.cs" />
4040
<Compile Include="Extensions\UnitTestOutcomeExtensions.cs" />
41+
<Compile Include="Helpers\DictionaryHelper.cs" />
4142
<Compile Include="Helpers\RunSettingsUtilities.cs" />
4243
<Compile Include="Helpers\TestRunParameters.cs" />
4344
<Compile Include="MSTestDiscoverer.cs" />
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
namespace Microsoft.VisualStudio.TestPlatform.MSTestAdapter.UnitTests
5+
{
6+
extern alias FrameworkV1;
7+
extern alias FrameworkV2;
8+
9+
using System;
10+
using System.Collections.Generic;
11+
using System.Linq;
12+
using System.Reflection;
13+
using FluentAssertions;
14+
using Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter;
15+
using Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.Helpers;
16+
using Moq;
17+
18+
using TestableImplementations;
19+
using Assert = FrameworkV1::Microsoft.VisualStudio.TestTools.UnitTesting.Assert;
20+
using CollectionAssert = FrameworkV1::Microsoft.VisualStudio.TestTools.UnitTesting.CollectionAssert;
21+
using TestClass = FrameworkV1::Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute;
22+
using TestCleanup = FrameworkV1::Microsoft.VisualStudio.TestTools.UnitTesting.TestCleanupAttribute;
23+
using TestInitialize = FrameworkV1::Microsoft.VisualStudio.TestTools.UnitTesting.TestInitializeAttribute;
24+
using TestMethod = FrameworkV1::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute;
25+
using UTF = FrameworkV2::Microsoft.VisualStudio.TestTools.UnitTesting;
26+
27+
[TestClass]
28+
public class DictionaryHelperTests
29+
{
30+
[TestMethod]
31+
public void ConcatenatingDictionariesReturnsEmptyDictionaryWhenBothSidesAreNullOrEmpty()
32+
{
33+
Dictionary<string, string> source = null;
34+
35+
var overwrite = new Dictionary<string, string>();
36+
37+
var actual = source.ConcatWithOverwrites(overwrite, nameof(source), nameof(overwrite));
38+
var expected = new Dictionary<string, string>();
39+
40+
actual.Should().BeEquivalentTo(expected);
41+
}
42+
43+
[TestMethod]
44+
public void ConcatenatingDictionariesReturnsSourceSideWhenOverwriteIsNullOrEmpty()
45+
{
46+
var source = new Dictionary<string, string>
47+
{
48+
["aaa"] = "source",
49+
["bbb"] = "source",
50+
};
51+
52+
Dictionary<string, string> overwrite = null;
53+
54+
var actual = source.ConcatWithOverwrites(overwrite, nameof(source), nameof(overwrite));
55+
56+
actual.Should().BeEquivalentTo(source);
57+
}
58+
59+
[TestMethod]
60+
public void ConcatenatingDictionariesReturnsOverwriteSideWhenSourceIsNullOrEmpty()
61+
{
62+
Dictionary<string, string> source = null;
63+
64+
var overwrite = new Dictionary<string, string>
65+
{
66+
["bbb"] = "overwrite",
67+
["ccc"] = "overwrite",
68+
};
69+
70+
var actual = source.ConcatWithOverwrites(overwrite, nameof(source), nameof(overwrite));
71+
72+
actual.Should().BeEquivalentTo(overwrite);
73+
}
74+
75+
[TestMethod]
76+
public void ConcatenatingDictionariesShouldMergeThemAndTakeDuplicateKeysFromOverwrite()
77+
{
78+
var source = new Dictionary<string, string>
79+
{
80+
["aaa"] = "source",
81+
["bbb"] = "source",
82+
};
83+
84+
var overwrite = new Dictionary<string, string>
85+
{
86+
["bbb"] = "overwrite",
87+
["ccc"] = "overwrite",
88+
};
89+
90+
var actual = source.ConcatWithOverwrites(overwrite, nameof(source), nameof(overwrite));
91+
var expected = new Dictionary<string, string>
92+
{
93+
// this is only present in source, take it
94+
["aaa"] = "source",
95+
96+
// this is present in source and overwrite, take it from overwrite
97+
["bbb"] = "overwrite",
98+
99+
// this is present only in overwrite, take it from overwrite
100+
["ccc"] = "overwrite",
101+
};
102+
103+
actual.Should().BeEquivalentTo(expected);
104+
}
105+
}
106+
}

test/UnitTests/MSTest.CoreAdapter.Unit.Tests/MSTest.CoreAdapter.Unit.Tests.csproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
<HintPath>$(TestFxRoot)packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll</HintPath>
4040
<Private>True</Private>
4141
</Reference>
42+
<Reference Include="FluentAssertions, Version=5.10.3.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
43+
<HintPath>..\..\..\packages\FluentAssertions.5.10.3\lib\net45\FluentAssertions.dll</HintPath>
44+
</Reference>
4245
<Reference Include="Microsoft.TestPlatform.CoreUtilities, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
4346
<HintPath>..\..\..\packages\Microsoft.TestPlatform.ObjectModel.$(TestPlatformVersion)\lib\net451\Microsoft.TestPlatform.CoreUtilities.dll</HintPath>
4447
</Reference>
@@ -62,9 +65,13 @@
6265
<Reference Include="System.Collections.Immutable, Version=1.2.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
6366
<HintPath>..\..\..\packages\System.Collections.Immutable.1.5.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
6467
</Reference>
68+
<Reference Include="System.Configuration" />
6569
<Reference Include="System.Reflection.Metadata, Version=1.4.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
6670
<HintPath>..\..\..\packages\System.Reflection.Metadata.1.6.0\lib\portable-net45+win8\System.Reflection.Metadata.dll</HintPath>
6771
</Reference>
72+
<Reference Include="System.ValueTuple, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
73+
<HintPath>..\..\..\packages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath>
74+
</Reference>
6875
<Reference Include="System.Xml" />
6976
<Reference Include="System.Xml.Linq" />
7077
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
@@ -99,6 +106,7 @@
99106
<Compile Include="Extensions\TestContextExtensionsTests.cs" />
100107
<Compile Include="Extensions\TestResultExtensionsTests.cs" />
101108
<Compile Include="Extensions\UnitTestOutcomeExtensionsTests.cs" />
109+
<Compile Include="Helpers\DictionaryHelperTests.cs" />
102110
<Compile Include="Helpers\ReflectHelperTests.cs" />
103111
<Compile Include="Helpers\RunSettingsUtilitiesTests.cs" />
104112
<Compile Include="Helpers\UnitTestOutcomeHelperTests.cs" />
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<packages>
33
<package id="Castle.Core" version="3.3.3" targetFramework="net452" />
4-
<package id="Microsoft.TestPlatform.ObjectModel" version="16.10.0-preview-20210204-01" targetFramework="net452" />
4+
<package id="FluentAssertions" version="5.10.3" targetFramework="net452" />
55
<package id="Microsoft.TestPlatform.AdapterUtilities" version="16.10.0-preview-20210204-01" targetFramework="net452" />
6+
<package id="Microsoft.TestPlatform.ObjectModel" version="16.10.0-preview-20210204-01" targetFramework="net452" />
67
<package id="Moq" version="4.5.21" targetFramework="net452" />
78
<package id="NuGet.Frameworks" version="5.0.0" targetFramework="net452" />
89
<package id="StyleCop.Analyzers" version="1.0.0" targetFramework="net452" developmentDependency="true" />
910
<package id="System.Collections.Immutable" version="1.5.0" targetFramework="net452" />
1011
<package id="System.Reflection.Metadata" version="1.6.0" targetFramework="net452" />
12+
<package id="System.ValueTuple" version="4.4.0" targetFramework="net452" />
1113
</packages>

0 commit comments

Comments
 (0)