Skip to content

Commit fbf6da3

Browse files
committed
add integration test (and fix CI)
1 parent 4ff8661 commit fbf6da3

2 files changed

Lines changed: 69 additions & 4 deletions

File tree

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using System;
2+
using System.Buffers;
3+
using System.Text;
4+
using System.Threading.Tasks;
5+
using Xunit;
6+
7+
namespace StackExchange.Redis.Tests;
8+
9+
/// <summary>
10+
/// Round-trips a multi-segment <see cref="ReadOnlySequence{T}"/>-backed <see cref="RedisValue"/>
11+
/// (<see cref="RedisValue.StorageType.Sequence"/>) through the shared in-process server via
12+
/// StringSet/StringGet, exercising the segmented write path in <c>MessageWriter</c>.
13+
/// </summary>
14+
public class RedisValueSequenceServerTests(ITestOutputHelper output, InProcServerFixture fixture) : TestBase(output, fixture)
15+
{
16+
// one segment per byte => a genuinely multi-segment sequence (StorageType.Sequence)
17+
private static RedisValue MultiSegment(byte[] payload)
18+
{
19+
var chunks = new ReadOnlyMemory<byte>[payload.Length];
20+
for (int i = 0; i < payload.Length; i++)
21+
{
22+
chunks[i] = new ReadOnlyMemory<byte>(payload, i, 1);
23+
}
24+
return FragmentedSegment<byte>.Create(chunks);
25+
}
26+
27+
[Fact]
28+
public async Task StringSet_MultiSegmentSequence_RoundTrips()
29+
{
30+
await using var conn = Create();
31+
var db = conn.GetDatabase();
32+
var key = Me();
33+
db.KeyDelete(key, CommandFlags.FireAndForget);
34+
35+
var payload = Encoding.UTF8.GetBytes("the quick brown fox jumps over the lazy dog");
36+
RedisValue value = MultiSegment(payload);
37+
Assert.Equal(RedisValue.StorageType.Sequence, value.Type);
38+
39+
Assert.True(db.StringSet(key, value));
40+
41+
var roundTripped = db.StringGet(key);
42+
Assert.Equal(payload, (byte[]?)roundTripped);
43+
}
44+
45+
[Fact]
46+
public async Task StringSetAsync_MultiSegmentSequence_RoundTrips()
47+
{
48+
await using var conn = Create();
49+
var db = conn.GetDatabase();
50+
var key = Me();
51+
await db.KeyDeleteAsync(key);
52+
53+
var payload = Encoding.UTF8.GetBytes("a multi-segment sequence payload long enough to span several segments");
54+
RedisValue value = MultiSegment(payload);
55+
Assert.Equal(RedisValue.StorageType.Sequence, value.Type);
56+
57+
Assert.True(await db.StringSetAsync(key, value));
58+
59+
var roundTripped = await db.StringGetAsync(key);
60+
Assert.Equal(payload, (byte[]?)roundTripped);
61+
}
62+
}

tests/StackExchange.Redis.Tests/RedisValueSequenceTests.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,8 @@ public void MultiSegmentSequence_CompareTo_EqualContentDifferentBoundaries()
182182
{
183183
// identical content, but segmented differently on each side - the tandem walk must still see equality
184184
var bytes = Encoding.UTF8.GetBytes("the quick brown fox");
185-
RedisValue a = FragmentedSegment<byte>.Create(bytes[..4], bytes[4..11], bytes[11..]);
186-
RedisValue b = FragmentedSegment<byte>.Create(bytes[..2], bytes[2..9], bytes[9..15], bytes[15..]);
185+
RedisValue a = FragmentedSegment<byte>.Create(Mem(bytes, 0, 4), Mem(bytes, 4, 7), Mem(bytes, 11, bytes.Length - 11));
186+
RedisValue b = FragmentedSegment<byte>.Create(Mem(bytes, 0, 2), Mem(bytes, 2, 7), Mem(bytes, 9, 6), Mem(bytes, 15, bytes.Length - 15));
187187
Assert.Equal(RedisValue.StorageType.Sequence, a.Type);
188188
Assert.Equal(RedisValue.StorageType.Sequence, b.Type);
189189

@@ -198,8 +198,8 @@ public void MultiSegmentSequence_CompareTo_DifferenceAcrossBoundaries()
198198
// the differing byte (index 5: 'f' vs 'X') sits in a different segment on each side
199199
var x = Encoding.UTF8.GetBytes("abcdefgh");
200200
var y = Encoding.UTF8.GetBytes("abcdeXgh");
201-
RedisValue sx = FragmentedSegment<byte>.Create(x[..3], x[3..]); // [abc][defgh]
202-
RedisValue sy = FragmentedSegment<byte>.Create(y[..6], y[6..]); // [abcdeX][gh]
201+
RedisValue sx = FragmentedSegment<byte>.Create(Mem(x, 0, 3), Mem(x, 3, x.Length - 3)); // [abc][defgh]
202+
RedisValue sy = FragmentedSegment<byte>.Create(Mem(y, 0, 6), Mem(y, 6, y.Length - 6)); // [abcdeX][gh]
203203

204204
int expected = Math.Sign(((ReadOnlySpan<byte>)x).SequenceCompareTo(y)); // 'f' > 'X' => positive
205205
Assert.Equal(expected, Math.Sign(sx.CompareTo(sy)));
@@ -225,4 +225,7 @@ private static RedisValue SplitEveryByte(byte[] bytes)
225225
}
226226
return FragmentedSegment<byte>.Create(chunks);
227227
}
228+
229+
// a slice of the source as ReadOnlyMemory (no array allocation, and avoids range syntax for net481)
230+
private static ReadOnlyMemory<byte> Mem(byte[] source, int start, int length) => new(source, start, length);
228231
}

0 commit comments

Comments
 (0)