Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Single Threaded Client Usage Issues in Parallel ACL SETUSER Tests #1064

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 12 additions & 19 deletions test/Garnet.test/Resp/ACL/ParallelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ public void ParallelPasswordHashTest(int degreeOfParallelism, int iterationsPerS
/// <summary>
/// Tests that ACL SETUSER works in parallel without corrupting the user's ACL.
///
/// Test launches multiple clients that apply two simple ACL changes to the same user many times in parallel.
/// Validates that ACL result after each execution is one of the possible valid responses.
/// Test launches multiple single-threaded clients that apply two simple ACL changes to the same user many times
/// in parallel. Validates that ACL result after each execution is one of the possible valid responses.
///
/// Race conditions are not deterministic so test uses repeat.
///
Expand All @@ -90,6 +90,7 @@ public async Task ParallelAclSetUserTest(int degreeOfParallelism, int iterations
// This is a combination of the two commands above indicative of threading issues.
string inactiveUserWithGet = $"user {TestUserA} off #{DummyPasswordHash} +get";

// Use client with support for single thread.
using var c = TestUtils.GetGarnetClientSession();
c.Connect();
_ = await c.ExecuteAsync(activeUserWithGetCommand.Split(" "));
Expand All @@ -101,9 +102,8 @@ await Parallel.ForAsync(0, degreeOfParallelism, async (t, state) =>

for (uint i = 0; i < iterationsPerSession; i++)
{
await Task.WhenAll(
c.ExecuteAsync(activeUserWithGetCommand.Split(" ")),
c.ExecuteAsync(inactiveUserWithoutGetCommand.Split(" ")));
await c.ExecuteAsync(activeUserWithGetCommand.Split(" "));
await c.ExecuteAsync(inactiveUserWithoutGetCommand.Split(" "));

var aclListResponse = await c.ExecuteForArrayAsync("ACL", "LIST");

Expand All @@ -119,31 +119,24 @@ await Task.WhenAll(
/// <summary>
/// Tests that ACL SETUSER works in parallel without fatal contention on user in ACL map.
///
/// Test launches multiple clients that apply the same ACL change to the same user. Creates race to become the
/// the first client to add the user to the ACL. Throws after initial insert into ACL if threading issues exist.
/// Test launches multiple single-threaded clients that apply the same ACL change to the same user. Creates race
/// to become the first client to add the user to the ACL. Throws after initial insert into ACL if threading issues exist.
///
/// Race conditions are not deterministic so test uses repeat.
///
/// </summary>
[TestCase(128, 2048)]
[TestCase(128)]
[Repeat(5)]
public async Task ParallelAclSetUserAvoidsMapContentionTest(int degreeOfParallelism, int iterationsPerSession)
public async Task ParallelAclSetUserAvoidsMapContentionTest(int degreeOfParallelism)
{
string command1 = $"ACL SETUSER {TestUserA} on >{DummyPassword}";
string setUserCommand = $"ACL SETUSER {TestUserA} on >{DummyPassword}";

await Parallel.ForAsync(0, degreeOfParallelism, async (t, state) =>
{
// Use client with support for single thread.
using var c = TestUtils.GetGarnetClientSession();
c.Connect();

List<Task> tasks = new();
for (uint i = 0; i < iterationsPerSession; i++)
{
// Creates race between threads contending for first insert into ACL. Throws after first ACL insert.
tasks.Add(c.ExecuteAsync(command1.Split(" ")));
}

await Task.WhenAll(tasks);
await c.ExecuteAsync(setUserCommand.Split(" "));
});

ClassicAssert.Pass();
Expand Down