Skip to content

Commit d22a096

Browse files
committed
ensure SORT_RO parse correctly; impact: Execute would not apply command-map rename correctly otherwise
1 parent 239ad24 commit d22a096

2 files changed

Lines changed: 53 additions & 0 deletions

File tree

src/StackExchange.Redis/Enums/RedisCommand.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ internal enum RedisCommand
5959
ECHO,
6060
EVAL,
6161
EVALSHA,
62+
[AsciiHash("EVAL_RO")]
6263
EVAL_RO,
64+
[AsciiHash("EVALSHA_RO")]
6365
EVALSHA_RO,
6466
EXEC,
6567
EXISTS,
@@ -208,6 +210,7 @@ internal enum RedisCommand
208210
SMISMEMBER,
209211
SMOVE,
210212
SORT,
213+
[AsciiHash("SORT_RO")]
211214
SORT_RO,
212215
SPOP,
213216
SPUBLISH,
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System;
2+
using System.Text;
3+
using Xunit;
4+
5+
namespace StackExchange.Redis.Tests;
6+
7+
/// <summary>
8+
/// Pure unit tests (no server) over the default <see cref="CommandMap"/>, pinning the exact RESP
9+
/// bulk-string chunk that would be written to the wire for a given <see cref="RedisCommand"/>.
10+
/// </summary>
11+
public class CommandMapUnitTests
12+
{
13+
[Theory]
14+
// a vanilla command, for baseline
15+
[InlineData(RedisCommand.GET, "$3\r\nGET\r\n")]
16+
[InlineData(RedisCommand.ZREMRANGEBYSCORE, "$16\r\nZREMRANGEBYSCORE\r\n")]
17+
// the read-only variants: the wire name uses an UNDERSCORE (these are the real Redis command
18+
// names: EVAL_RO / EVALSHA_RO / SORT_RO), which is what command.ToString() yields today.
19+
[InlineData(RedisCommand.EVAL_RO, "$7\r\nEVAL_RO\r\n")]
20+
[InlineData(RedisCommand.EVALSHA_RO, "$10\r\nEVALSHA_RO\r\n")]
21+
[InlineData(RedisCommand.SORT_RO, "$7\r\nSORT_RO\r\n")]
22+
public void DefaultCommandMap_GetResp_ProducesExpectedWireBytes(object command, string expectedResp)
23+
{
24+
// command is boxed as object because RedisCommand is internal (less accessible than this public method)
25+
ReadOnlySpan<byte> resp = CommandMap.Default.GetResp((RedisCommand)command);
26+
Assert.Equal(expectedResp, Encoding.ASCII.GetString(resp));
27+
}
28+
29+
[Theory]
30+
// vanilla command, for baseline
31+
[InlineData("GET", RedisCommand.GET)]
32+
[InlineData("ZREMRANGEBYSCORE", RedisCommand.ZREMRANGEBYSCORE)]
33+
// the underscore variants: parsing the real Redis wire name (with an underscore) MUST round-trip
34+
// back to the matching enum value. This guards against the AsciiHash code-gen inferring '_' -> '-'
35+
// (which would only recognise "EVAL-RO" and fail to parse the actual "EVAL_RO").
36+
[InlineData("EVAL_RO", RedisCommand.EVAL_RO)]
37+
[InlineData("EVALSHA_RO", RedisCommand.EVALSHA_RO)]
38+
[InlineData("SORT_RO", RedisCommand.SORT_RO)]
39+
public void TryParseCI_ParsesRealWireName(string name, object expected)
40+
{
41+
var expectedCommand = (RedisCommand)expected;
42+
43+
Assert.True(RedisCommandMetadata.TryParseCI(name.AsSpan(), out var fromChars), $"char parse failed for '{name}'");
44+
Assert.Equal(expectedCommand, fromChars);
45+
46+
ReadOnlySpan<byte> bytes = Encoding.ASCII.GetBytes(name);
47+
Assert.True(RedisCommandMetadata.TryParseCI(bytes, out var fromBytes), $"byte parse failed for '{name}'");
48+
Assert.Equal(expectedCommand, fromBytes);
49+
}
50+
}

0 commit comments

Comments
 (0)