Skip to content

ConcurrentDictionary Test Coverage | TestGetOrAddOrUpdate #83429

@Notheisz57

Description

@Notheisz57

Code for context:

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
public static void TestGetOrAdd()
{
TestGetOrAddOrUpdate(1, 1, 1, 10000, true);
TestGetOrAddOrUpdate(5, 1, 1, 10000, true);
TestGetOrAddOrUpdate(1, 1, 2, 5000, true);
TestGetOrAddOrUpdate(1, 1, 5, 2000, true);
TestGetOrAddOrUpdate(4, 0, 4, 2000, true);
TestGetOrAddOrUpdate(16, 31, 4, 2000, true);
TestGetOrAddOrUpdate(64, 5, 5, 5000, true);
TestGetOrAddOrUpdate(5, 5, 5, 25000, true);
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
public static void TestAddOrUpdate()
{
TestGetOrAddOrUpdate(1, 1, 1, 10000, false);
TestGetOrAddOrUpdate(5, 1, 1, 10000, false);
TestGetOrAddOrUpdate(1, 1, 2, 5000, false);
TestGetOrAddOrUpdate(1, 1, 5, 2000, false);
TestGetOrAddOrUpdate(4, 0, 4, 2000, false);
TestGetOrAddOrUpdate(16, 31, 4, 2000, false);
TestGetOrAddOrUpdate(64, 5, 5, 5000, false);
TestGetOrAddOrUpdate(5, 5, 5, 25000, false);
}
private static void TestGetOrAddOrUpdate(int cLevel, int initSize, int threads, int addsPerThread, bool isAdd)
{
ConcurrentDictionary<int, int> dict = new ConcurrentDictionary<int, int>(cLevel, 1);
int count = threads;
using (ManualResetEvent mre = new ManualResetEvent(false))
{
for (int i = 0; i < threads; i++)
{
int ii = i;
Task.Run(
() =>
{
for (int j = 0; j < addsPerThread; j++)
{
if (isAdd)
{
//call one of the overloads of GetOrAdd
switch (j % 3)
{
case 0:
dict.GetOrAdd(j, -j);
break;
case 1:
dict.GetOrAdd(j, x => -x);
break;
case 2:
dict.GetOrAdd(j, (x,m) => x * m, -1);
break;
}
}
else
{
switch (j % 3)
{
case 0:
dict.AddOrUpdate(j, -j, (k, v) => -j);
break;
case 1:
dict.AddOrUpdate(j, (k) => -k, (k, v) => -k);
break;
case 2:
dict.AddOrUpdate(j, (k,m) => k*m, (k, v, m) => k * m, -1);
break;
}
}
}
if (Interlocked.Decrement(ref count) == 0) mre.Set();
});
}
mre.WaitOne();
}
foreach (var pair in dict)
{
Assert.Equal(pair.Key, -pair.Value);
}
List<int> gotKeys = new List<int>();
foreach (var pair in dict)
gotKeys.Add(pair.Key);
gotKeys.Sort();
List<int> expectKeys = new List<int>();
for (int i = 0; i < addsPerThread; i++)
expectKeys.Add(i);
Assert.Equal(expectKeys.Count, gotKeys.Count);
for (int i = 0; i < expectKeys.Count; i++)
{
Assert.True(expectKeys[i].Equals(gotKeys[i]),
string.Format("* Test '{4}': Level={0}, initSize={1}, threads={2}, addsPerThread={3})" + Environment.NewLine +
"> FAILED. The set of keys in the dictionary is are not the same as the expected.",
cLevel, initSize, threads, addsPerThread, isAdd ? "GetOrAdd" : "GetOrUpdate"));
}
// Finally, let's verify that the count is reported correctly.
Assert.Equal(addsPerThread, dict.Count);
Assert.Equal(addsPerThread, dict.ToArray().Length);
}

While the other switch-case statements make use of the lambda arguments, the case statement on line 547 does not:

Should this test case be more thorough/complete in testing these overloads and their lambda arguments, or is this test case good enough as it is?

Metadata

Metadata

Labels

area-System.Collectionsin-prThere is an active PR which will close this issue when it is mergedtest-enhancementImprovements of test source code

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions