From 790d92cec2ea6cb2785dbf7271a93134f762dbfa Mon Sep 17 00:00:00 2001 From: prvyk Date: Sat, 5 Apr 2025 14:37:35 +0300 Subject: [PATCH] Fix CanDoSRANDMEMBERWithCountCommandLC test Fix remaining Encoding.ASCII.GetString usages. --- test/Garnet.test/GarnetServerConfigTests.cs | 1 + .../RespBlockingCollectionTests.cs | 7 +- test/Garnet.test/RespSetTest.cs | 75 +++++-------------- test/Garnet.test/RespSortedSetTests.cs | 11 +-- test/Garnet.test/RespTests.cs | 15 ++-- test/Garnet.test/TestUtils.cs | 1 - 6 files changed, 39 insertions(+), 71 deletions(-) diff --git a/test/Garnet.test/GarnetServerConfigTests.cs b/test/Garnet.test/GarnetServerConfigTests.cs index 760248b3ad1..7c8b059066e 100644 --- a/test/Garnet.test/GarnetServerConfigTests.cs +++ b/test/Garnet.test/GarnetServerConfigTests.cs @@ -784,6 +784,7 @@ public async Task MultiTcpSocketTest() var hostname = TestUtils.GetHostName(); var addresses = Dns.GetHostAddresses(hostname); addresses = [.. addresses, IPAddress.IPv6Loopback, IPAddress.Loopback]; + addresses = [.. addresses.Distinct()]; var endpoints = addresses.Select(address => new IPEndPoint(address, TestUtils.TestPort)).ToArray(); var server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, endpoints: endpoints); diff --git a/test/Garnet.test/RespBlockingCollectionTests.cs b/test/Garnet.test/RespBlockingCollectionTests.cs index 7b7f193be27..f48f4c66b76 100644 --- a/test/Garnet.test/RespBlockingCollectionTests.cs +++ b/test/Garnet.test/RespBlockingCollectionTests.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. using System; -using System.Text; using System.Threading; using System.Threading.Tasks; using Garnet.server; @@ -444,8 +443,7 @@ public async Task BasicBzmpopWithExpireItemsTest(string mode) using var lcr = TestUtils.CreateRequest(); var response = lcr.SendCommand($"BZMPOP 1 1 {key} {mode}"); var expectedResponse = "$-1\r\n"; - var actualValue = Encoding.ASCII.GetString(response).Substring(0, expectedResponse.Length); - ClassicAssert.AreEqual(expectedResponse, actualValue); + TestUtils.AssertEqualUpToExpectedLength(expectedResponse, response); } [Test] @@ -551,8 +549,7 @@ public async Task BasicBzpopMinMaxWithExpireItemsTest(string command) using var lcr = TestUtils.CreateRequest(); var response = lcr.SendCommand($"{command} {key} 1"); var expectedResponse = "$-1\r\n"; - var actualValue = Encoding.ASCII.GetString(response).Substring(0, expectedResponse.Length); - ClassicAssert.AreEqual(expectedResponse, actualValue); + TestUtils.AssertEqualUpToExpectedLength(expectedResponse, response); } [Test] diff --git a/test/Garnet.test/RespSetTest.cs b/test/Garnet.test/RespSetTest.cs index 171f1d59ed8..23a1961866c 100644 --- a/test/Garnet.test/RespSetTest.cs +++ b/test/Garnet.test/RespSetTest.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using Garnet.common; using Garnet.server; using NUnit.Framework; using NUnit.Framework.Legacy; @@ -1007,7 +1008,7 @@ public void CanDoSCARDCommandsLC() } [Test] - public void CanDoSRANDMEMBERWithCountCommandLC() + public unsafe void CanDoSRANDMEMBERWithCountCommandLC() { var myset = new HashSet { "one", "two", "three", "four", "five" }; @@ -1025,43 +1026,31 @@ public void CanDoSRANDMEMBERWithCountCommandLC() CreateLongSet(); response = lightClientRequest.SendCommand("SRANDMEMBER myset", 1); - var strLen = Encoding.ASCII.GetString(response).Substring(1, 1); - var item = Encoding.ASCII.GetString(response).Substring(4, Int32.Parse(strLen)); + var strLen = Encoding.ASCII.GetString(response, 1, 1); + var item = Encoding.ASCII.GetString(response, 4, int.Parse(strLen)); ClassicAssert.IsTrue(myset.Contains(item)); // Get three random members response = lightClientRequest.SendCommand("SRANDMEMBER myset 3", 3); - TestUtils.AssertEqualUpToExpectedLength("*", response); - - var strResponse = Encoding.ASCII.GetString(response); - var arrLenEndIdx = strResponse.IndexOf("\r\n", StringComparison.InvariantCultureIgnoreCase); - ClassicAssert.IsTrue(arrLenEndIdx > 1); - - var strArrLen = strResponse.AsSpan().Slice(1, arrLenEndIdx - 1); - ClassicAssert.IsTrue(int.TryParse(strArrLen, out var arrLen)); - ClassicAssert.AreEqual(3, arrLen); + TestUtils.AssertEqualUpToExpectedLength("*3\r\n", response); // Get 6 random members and verify that at least two elements are the same response = lightClientRequest.SendCommand("SRANDMEMBER myset -6", 6); - var strReponse = Encoding.ASCII.GetString(response); - arrLenEndIdx = strReponse.IndexOf("\r\n", StringComparison.InvariantCultureIgnoreCase); - strArrLen = strReponse.AsSpan().Slice(1, arrLenEndIdx - 1); - ClassicAssert.IsTrue(int.TryParse(strArrLen, out arrLen)); - - var members = new HashSet(); - var repeatedMembers = false; - for (var i = 0; i < arrLen; i++) + TestUtils.AssertEqualUpToExpectedLength("*6\r\n", response); + + string[] results; + + fixed (byte* p = &response[0]) { - var member = strReponse.Substring(arrLenEndIdx + 2, response.Length - arrLenEndIdx - 5); - if (members.Contains(member)) - { - repeatedMembers = true; - break; - } - members.Add(member); + var ptr = p; + ClassicAssert.IsTrue( + RespReadUtils.TryReadStringArrayWithLengthHeader(out results, ref ptr, + p + (Garnet.common.NumUtils.MaximumFormatInt64Length * 10)) + ); } - ClassicAssert.IsTrue(repeatedMembers, "At least two members are repeated."); + ClassicAssert.IsTrue(results.Distinct().Count() != results.Length, + "At least two members are repeated."); } [Test] @@ -1096,15 +1085,7 @@ public void CanDoSPOPWithCountCommandLC() var lightClientRequest = TestUtils.CreateRequest(); var response = lightClientRequest.SendCommand("SPOP myset 3", 3); - TestUtils.AssertEqualUpToExpectedLength("*", response); - - var strResponse = Encoding.ASCII.GetString(response); - var arrLenEndIdx = strResponse.IndexOf("\r\n", StringComparison.InvariantCultureIgnoreCase); - ClassicAssert.IsTrue(arrLenEndIdx > 1); - - var strArrLen = strResponse.AsSpan().Slice(1, arrLenEndIdx - 1); - ClassicAssert.IsTrue(int.TryParse(strArrLen, out var arrLen)); - ClassicAssert.AreEqual(3, arrLen); + TestUtils.AssertEqualUpToExpectedLength("*3\r\n", response); response = lightClientRequest.SendCommands("SCARD myset", "PING", 1, 1); var expectedResponse = ":2\r\n+PONG\r\n"; @@ -1112,15 +1093,7 @@ public void CanDoSPOPWithCountCommandLC() // Test for popping set until empty response = lightClientRequest.SendCommand("SPOP myset 2", 2); - TestUtils.AssertEqualUpToExpectedLength("*", response); - - strResponse = Encoding.ASCII.GetString(response); - arrLenEndIdx = strResponse.IndexOf("\r\n", StringComparison.InvariantCultureIgnoreCase); - ClassicAssert.IsTrue(arrLenEndIdx > 1); - - strArrLen = strResponse.AsSpan().Slice(1, arrLenEndIdx - 1); - ClassicAssert.IsTrue(int.TryParse(strArrLen, out arrLen)); - ClassicAssert.AreEqual(2, arrLen); + TestUtils.AssertEqualUpToExpectedLength("*2\r\n", response); } [Test] @@ -1131,15 +1104,7 @@ public void CanDoSPOPWithMoreCountThanSetSizeCommandLC() var lightClientRequest = TestUtils.CreateRequest(); var response = lightClientRequest.SendCommand("SPOP myset 10", 5); - TestUtils.AssertEqualUpToExpectedLength("*", response); - - var strResponse = Encoding.ASCII.GetString(response); - var arrLenEndIdx = strResponse.IndexOf("\r\n", StringComparison.InvariantCultureIgnoreCase); - ClassicAssert.IsTrue(arrLenEndIdx > 1); - - var strArrLen = strResponse.AsSpan().Slice(1, arrLenEndIdx - 1); - ClassicAssert.IsTrue(int.TryParse(strArrLen, out var arrLen)); - ClassicAssert.IsTrue(arrLen == 5); + TestUtils.AssertEqualUpToExpectedLength("*5\r\n", response); var lightClientRequest2 = TestUtils.CreateRequest(); response = lightClientRequest2.SendCommand("SADD myset one"); diff --git a/test/Garnet.test/RespSortedSetTests.cs b/test/Garnet.test/RespSortedSetTests.cs index a814ef343a1..8c31cab6a85 100644 --- a/test/Garnet.test/RespSortedSetTests.cs +++ b/test/Garnet.test/RespSortedSetTests.cs @@ -4208,15 +4208,16 @@ public void CanUseZRandMember(int bytesSent) _ = lightClientRequest.SendCommand("ZADD dadi 1 uno 2 due 3 tre 4 quattro 5 cinque 6 six 7 sept 8 huit 9 nough 10 dis"); // ZRANDMEMBER - var s = Encoding.ASCII.GetString(lightClientRequest.SendCommandChunks("ZRANDMEMBER dadi", bytesSent)); - int startIndexField = s.IndexOf('\n') + 1; - int endIndexField = s.IndexOf('\n', startIndexField) - 1; - string memberValue = s.Substring(startIndexField, endIndexField - startIndexField); + var response = lightClientRequest.SendCommandChunks("ZRANDMEMBER dadi", bytesSent); + var s = Encoding.ASCII.GetString(response, 0, Garnet.common.NumUtils.MaximumFormatInt64Length); + var startIndexField = s.IndexOf('\n') + 1; + var endIndexField = s.IndexOf('\n', startIndexField) - 1; + var memberValue = s.Substring(startIndexField, endIndexField - startIndexField); var foundInSet = ("uno due tre quattro cinque six sept huit nough dis").IndexOf(memberValue, StringComparison.InvariantCultureIgnoreCase); ClassicAssert.IsTrue(foundInSet >= 0); // ZRANDMEMBER count - var response = lightClientRequest.SendCommandChunks("ZRANDMEMBER dadi 5", bytesSent, 6); + response = lightClientRequest.SendCommandChunks("ZRANDMEMBER dadi 5", bytesSent, 6); var expectedResponse = "*5\r\n"; // 5 values TestUtils.AssertEqualUpToExpectedLength(expectedResponse, response); diff --git a/test/Garnet.test/RespTests.cs b/test/Garnet.test/RespTests.cs index dc55a6b56ef..bb8585f0431 100644 --- a/test/Garnet.test/RespTests.cs +++ b/test/Garnet.test/RespTests.cs @@ -4958,17 +4958,19 @@ public async Task ClientUnblockBasicTest(string clientType, string mode, bool ex // Start blocking client using var blockingClient = TestUtils.CreateRequest(); - var clientIdResponse = Encoding.ASCII.GetString(blockingClient.SendCommand("CLIENT ID")); + var clientIdResponse = Encoding.ASCII.GetString(blockingClient.SendCommand("CLIENT ID"), 0, + Garnet.common.NumUtils.MaximumFormatInt64Length * 2); var clientId = clientIdResponse.Substring(1, clientIdResponse.IndexOf("\r\n") - 1); + var isError = false; Task blockingTask = null; - bool isError = false; + if (clientType == "BLOCKING") { blockingTask = taskFactory.StartNew(() => { var startTime = Stopwatch.GetTimestamp(); var response = blockingClient.SendCommand("BLMPOP 10 1 keyA LEFT"); - if (Encoding.ASCII.GetString(response).Substring(0, "-UNBLOCKED".Length) == "-UNBLOCKED") + if (Encoding.ASCII.GetString(response, 0, "-UNBLOCKED".Length) == "-UNBLOCKED") { isError = true; } @@ -5019,14 +5021,17 @@ public async Task MultipleClientsUnblockAndAddTest(int numberOfItems) // Start blocking client using var blockingClient = TestUtils.CreateRequest(); - var clientIdResponse = Encoding.ASCII.GetString(blockingClient.SendCommand("CLIENT ID")); + var clientIdResponse = Encoding.ASCII.GetString(blockingClient.SendCommand("CLIENT ID"), 0, + Garnet.common.NumUtils.MaximumFormatInt64Length * 2); var clientId = clientIdResponse.Substring(1, clientIdResponse.IndexOf("\r\n") - 1); + ClassicAssert.IsTrue(long.TryParse(clientId, out _)); string blockingResult = null; var blockingTask = Task.Run(() => { var response = blockingClient.SendCommand($"BLMPOP 10 1 {key} LEFT COUNT 30"); - blockingResult = Encoding.ASCII.GetString(response); + blockingResult = Encoding.ASCII.GetString(response, 0, + Garnet.common.NumUtils.MaximumFormatInt64Length * (numberOfItems + 1)); }); // Wait for client to enter blocking state diff --git a/test/Garnet.test/TestUtils.cs b/test/Garnet.test/TestUtils.cs index 918fee535c9..f473b69f04f 100644 --- a/test/Garnet.test/TestUtils.cs +++ b/test/Garnet.test/TestUtils.cs @@ -80,7 +80,6 @@ internal static class TestUtils /// static readonly bool useTestLogger = false; - private static int procId = Process.GetCurrentProcess().Id; internal static string CustomRespCommandInfoJsonPath = "CustomRespCommandsInfo.json"; internal static string CustomRespCommandDocsJsonPath = "CustomRespCommandsDocs.json";