From 3ffd1aaece751073ec8dc6a1de1cb84e0fbb24ab Mon Sep 17 00:00:00 2001 From: Tal Zaccai Date: Tue, 28 May 2024 13:32:47 -0600 Subject: [PATCH] Applying some fixes to PR --- .../GarnetClientListCommands.cs | 25 ++- test/Garnet.test/RespListGarnetClientTests.cs | 147 +++++++++++------- 2 files changed, 98 insertions(+), 74 deletions(-) diff --git a/libs/client/GarnetClientAPI/GarnetClientListCommands.cs b/libs/client/GarnetClientAPI/GarnetClientListCommands.cs index 1f1a444cc1..8b05a2973f 100644 --- a/libs/client/GarnetClientAPI/GarnetClientListCommands.cs +++ b/libs/client/GarnetClientAPI/GarnetClientListCommands.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; using System.Threading.Tasks; @@ -42,22 +43,20 @@ public void ListLeftPush(string key, string element, Action /// The elements to be added. /// The callback function when operation completes. /// An optional context to correlate request to callback. - public void ListLeftPush(string key, List elements, Action callback, long context = 0) + public void ListLeftPush(string key, IEnumerable elements, Action callback, long context = 0) { ArgumentNullException.ThrowIfNull(key); ArgumentNullException.ThrowIfNull(elements); ArgumentNullException.ThrowIfNull(callback); - if (elements.Count == 0) + var arrElem = new[] { key }.Union(elements).ToArray(); + + if (arrElem.Length == 1) { throw new ArgumentException("The elements can't be empty.", nameof(elements)); } - elements.Insert(0, key); - - ExecuteForLongResult(callback, context, nameof(LPUSH), elements); - - elements.RemoveAt(0); + ExecuteForLongResult(callback, context, nameof(LPUSH), arrElem); } /// @@ -110,22 +109,20 @@ public void ListRightPush(string key, string element, Action /// The elements to be added. /// The callback function when operation completes. /// An optional context to correlate request to callback. - public void ListRightPush(string key, List elements, Action callback, long context = 0) + public void ListRightPush(string key, IEnumerable elements, Action callback, long context = 0) { ArgumentNullException.ThrowIfNull(key); ArgumentNullException.ThrowIfNull(elements); ArgumentNullException.ThrowIfNull(callback); - if (elements.Count == 0) + var arrElem = new[] { key }.Union(elements).ToArray(); + + if (arrElem.Length == 1) { throw new ArgumentException("The elements can't be empty.", nameof(elements)); } - elements.Insert(0, key); - - ExecuteForLongResult(callback, context, nameof(RPUSH), elements); - - elements.RemoveAt(0); + ExecuteForLongResult(callback, context, nameof(RPUSH), arrElem); } /// diff --git a/test/Garnet.test/RespListGarnetClientTests.cs b/test/Garnet.test/RespListGarnetClientTests.cs index 01e2245b7b..5fdb4a7802 100644 --- a/test/Garnet.test/RespListGarnetClientTests.cs +++ b/test/Garnet.test/RespListGarnetClientTests.cs @@ -1,138 +1,165 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +using System.Linq; using System.Threading; using System.Threading.Tasks; using Garnet.client; using NUnit.Framework; +using StackExchange.Redis; namespace Garnet.test { [TestFixture] public class RespListGarnetClientTests { - private GarnetServer _server; + private GarnetServer server; [OneTimeSetUp] public void Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - _server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true); - _server.Start(); + server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true); + server.Start(); + } + + private static object[] LeftPushTestCases = + [ + new object[] { "list1", new [] { "foo" }, new [] { "foo" } }, + new object[] { "list2", new [] { "foo", "baz" }, new [] { "baz", "foo" } }, + new object[] { "list1", new [] { "bar", "baz" }, new [] { "baz", "bar", "foo" } }, + new object[] { "list3", new [] { "foo", "bar", "baz" }, new [] { "baz", "bar", "foo" } }, + new object[] { "list2", new [] { "foo", "bar", "baz" }, new[] { "baz", "bar", "foo", "baz", "foo" } } + ]; + + private static object[] RightPushTestCases = + [ + new object[] { "list1", new [] { "foo" }, new [] { "foo" } }, + new object[] { "list2", new [] { "foo", "baz" }, new [] { "foo", "baz" } }, + new object[] { "list1", new [] { "bar", "baz" }, new [] { "foo", "bar", "baz" } }, + new object[] { "list3", new [] { "foo", "bar", "baz" }, new [] { "foo", "bar", "baz" } }, + new object[] { "list2", new [] { "foo", "bar", "baz" }, new[] { "foo", "baz", "foo", "bar", "baz" } } + ]; + + private static string GetTestKey(string key) + { + var testName = TestContext.CurrentContext.Test.MethodName; + return $"{testName}_{key}"; } [Test] - public void AddElementsToTheListHead_WithCallback() + [TestCaseSource(nameof(LeftPushTestCases))] + + public void AddElementsToTheListHead_WithCallback(string key, string[] elements, string[] expectedList) { // Arrange using var db = new GarnetClient(TestUtils.Address, TestUtils.Port); db.Connect(); - ManualResetEventSlim e = new(); + using ManualResetEventSlim e = new(); - // Act & Assert - db.ListLeftPush("list1", "foo", (_, returnValue, _) => - { - Assert.AreEqual(1, returnValue); - e.Set(); - }); + var isResultSet = false; + var actualListLength = 0L; - e.Wait(); - e.Reset(); + // Act & Assert + var testKey = GetTestKey(key); - db.ListLeftPush("list1", ["bar", "baz"], (_, returnValue, _) => + db.ListLeftPush(testKey, elements, (_, returnValue, _) => { - Assert.AreEqual(3, returnValue); + actualListLength = returnValue; + isResultSet = true; e.Set(); }); e.Wait(); - e.Reset(); - - db.ListLeftPush("list2", ["foo", "baz"], (_, returnValue, _) => - { - Assert.AreEqual(2, returnValue); - e.Set(); - }); + Assert.IsTrue(isResultSet); + Assert.AreEqual(expectedList.Length, actualListLength); - e.Wait(); - e.Reset(); - e.Dispose(); + ValidateListContent(testKey, expectedList); } [Test] - [TestCase("list3", new string[] { "foo", "bar" }, 2)] - [TestCase("list4", new string[] { "foo", "bar", "baz" }, 3)] - [TestCase("list3", new string[] { "baz" }, 3)] - [TestCase("list5", new string[] { "foo" }, 1)] - public async Task AddElementsToTheListHead_ReturnsListItemsCount(string key, string[] elements, int result) + [TestCaseSource(nameof(LeftPushTestCases))] + public async Task AddElementsToTheListHead_WithAsync(string key, string[] elements, string[] expectedList) { // Arrange using var db = new GarnetClient(TestUtils.Address, TestUtils.Port); await db.ConnectAsync(); // Act & Assert - Assert.AreEqual(result, await db.ListLeftPushAsync(key, elements)); + var testKey = GetTestKey(key); + + var actualListLength = await db.ListLeftPushAsync(testKey, elements); + Assert.AreEqual(expectedList.Length, actualListLength); + + ValidateListContent(testKey, expectedList); } [Test] - public void AddElementsToListTail_WithCallback() + [TestCaseSource(nameof(RightPushTestCases))] + public void AddElementsToListTail_WithCallback(string key, string[] elements, string[] expectedList) { // Arrange using var db = new GarnetClient(TestUtils.Address, TestUtils.Port); db.Connect(); - ManualResetEventSlim e = new(); + using ManualResetEventSlim e = new(); - // Act & Assert - db.ListRightPush("list6", "foo", (_, returnValue, _) => - { - Assert.AreEqual(1, returnValue); - e.Set(); - }); + var isResultSet = false; + var actualListLength = 0L; - e.Wait(); - e.Reset(); + // Act & Assert + var testKey = GetTestKey(key); - db.ListRightPush("list6", ["bar", "baz"], (_, returnValue, _) => + db.ListRightPush(testKey, elements, (_, returnValue, _) => { - Assert.AreEqual(3, returnValue); + actualListLength = returnValue; + isResultSet = true; e.Set(); }); e.Wait(); - e.Reset(); - - db.ListRightPush("list7", ["foo", "baz"], (_, returnValue, _) => - { - Assert.AreEqual(2, returnValue); - e.Set(); - }); + Assert.IsTrue(isResultSet); + Assert.AreEqual(expectedList.Length, actualListLength); - e.Wait(); - e.Reset(); - e.Dispose(); + ValidateListContent(testKey, expectedList); } [Test] - [TestCase("list8", new string[] { "foo", "bar" }, 2)] - [TestCase("list9", new string[] { "foo", "bar", "baz" }, 3)] - [TestCase("list8", new string[] { "baz" }, 3)] - [TestCase("list10", new string[] { "foo" }, 1)] - public async Task AddElementsToTheListTail_ReturnsListItemsCount(string key, string[] elements, int result) + [TestCaseSource(nameof(RightPushTestCases))] + public async Task AddElementsToTheListTail_WithAsync(string key, string[] elements, string[] expectedList) { // Arrange using var db = new GarnetClient(TestUtils.Address, TestUtils.Port); await db.ConnectAsync(); // Act & Assert - Assert.AreEqual(result, await db.ListRightPushAsync(key, elements)); + var testKey = GetTestKey(key); + + var actualListLength = await db.ListRightPushAsync(testKey, elements.ToArray()); + Assert.AreEqual(expectedList.Length, actualListLength); + + ValidateListContent(testKey, expectedList); + } + + private void ValidateListContent(string key, string[] expectedList) + { + // Using SE.Redis client to validate list content since Garnet client doesn't yet support LRANGE + using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); + var db = redis.GetDatabase(0); + + var actualElements = db.ListRange(key); + Assert.AreEqual(expectedList.Length, actualElements.Length); + for (var i = 0; i < actualElements.Length; i++) + { + Assert.AreEqual(expectedList[i], actualElements[i].ToString()); + } } [OneTimeTearDown] public void TearDown() { - _server.Dispose(); + server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); }