Skip to content

Commit 5613cc7

Browse files
committed
test fixture for in-proc; run with basic tests
1 parent 1ba7d0e commit 5613cc7

5 files changed

Lines changed: 95 additions & 11 deletions

File tree

tests/StackExchange.Redis.Tests/BasicOpTests.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,20 @@
77
namespace StackExchange.Redis.Tests;
88

99
[RunPerProtocol]
10-
public class BasicOpsTests(ITestOutputHelper output, SharedConnectionFixture fixture) : TestBase(output, fixture)
10+
public class BasicOpsTests(ITestOutputHelper output, SharedConnectionFixture fixture)
11+
: BasicOpsTestsBase(output, fixture, null)
12+
{
13+
}
14+
15+
[RunPerProtocol]
16+
public class InProcBasicOpsTests(ITestOutputHelper output, InProcServerFixture fixture)
17+
: BasicOpsTestsBase(output, null, fixture)
18+
{
19+
}
20+
21+
[RunPerProtocol]
22+
public abstract class BasicOpsTestsBase(ITestOutputHelper output, SharedConnectionFixture? connection, InProcServerFixture? server)
23+
: TestBase(output, connection, server)
1124
{
1225
[Fact]
1326
public async Task PingOnce()
@@ -472,6 +485,7 @@ public async Task WrappedDatabasePrefixIntegration()
472485
public async Task TransactionSync()
473486
{
474487
await using var conn = Create();
488+
Assert.SkipUnless(conn.RawConfig.CommandMap.IsAvailable(RedisCommand.MULTI), "MULTI is not available");
475489
var db = conn.GetDatabase();
476490

477491
RedisKey key = Me();
@@ -491,6 +505,8 @@ public async Task TransactionSync()
491505
public async Task TransactionAsync()
492506
{
493507
await using var conn = Create();
508+
Assert.SkipUnless(conn.RawConfig.CommandMap.IsAvailable(RedisCommand.MULTI), "MULTI is not available");
509+
494510
var db = conn.GetDatabase();
495511

496512
RedisKey key = Me();
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System;
2+
using StackExchange.Redis.Configuration;
3+
using Xunit;
4+
5+
[assembly: AssemblyFixture(typeof(StackExchange.Redis.Tests.InProcServerFixture))]
6+
7+
// ReSharper disable once CheckNamespace
8+
namespace StackExchange.Redis.Tests;
9+
10+
public class InProcServerFixture : IDisposable
11+
{
12+
private readonly InProcessTestServer _server = new();
13+
private readonly ConfigurationOptions _config;
14+
public InProcServerFixture()
15+
{
16+
_config = _server.GetClientConfig();
17+
Configuration = _config.ToString();
18+
}
19+
20+
public ConfigurationOptions Config => _config;
21+
22+
public string Configuration { get; }
23+
24+
public Tunnel? Tunnel => _server.Tunnel;
25+
26+
public void Dispose() => _server.Dispose();
27+
}

tests/StackExchange.Redis.Tests/HighIntegrityBasicOpsTests.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,8 @@ public class HighIntegrityBasicOpsTests(ITestOutputHelper output, SharedConnecti
66
{
77
internal override bool HighIntegrity => true;
88
}
9+
10+
public class InProcHighIntegrityBasicOpsTests(ITestOutputHelper output, InProcServerFixture fixture) : InProcBasicOpsTests(output, fixture)
11+
{
12+
internal override bool HighIntegrity => true;
13+
}

tests/StackExchange.Redis.Tests/TestBase.cs

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Runtime.CompilerServices;
88
using System.Threading;
99
using System.Threading.Tasks;
10+
using StackExchange.Redis.Configuration;
1011
using StackExchange.Redis.Profiling;
1112
using StackExchange.Redis.Tests.Helpers;
1213
using Xunit;
@@ -17,22 +18,35 @@ public abstract class TestBase : IDisposable
1718
{
1819
private ITestOutputHelper Output { get; }
1920
protected TextWriterOutputHelper Writer { get; }
20-
protected virtual string GetConfiguration() => GetDefaultConfiguration();
21+
protected virtual string GetConfiguration()
22+
{
23+
if (_inProcServerFixture != null)
24+
{
25+
return _inProcServerFixture.Configuration;
26+
}
27+
return GetDefaultConfiguration();
28+
}
2129
internal static string GetDefaultConfiguration() => TestConfig.Current.PrimaryServerAndPort;
2230

23-
private readonly SharedConnectionFixture? _fixture;
31+
private readonly SharedConnectionFixture? _sharedConnectionFixture;
32+
private readonly InProcServerFixture? _inProcServerFixture;
2433

25-
protected bool SharedFixtureAvailable => _fixture != null && _fixture.IsEnabled && !HighIntegrity;
34+
protected bool SharedFixtureAvailable => _sharedConnectionFixture != null && _sharedConnectionFixture.IsEnabled && !HighIntegrity;
2635

27-
protected TestBase(ITestOutputHelper output, SharedConnectionFixture? fixture = null)
36+
protected TestBase(ITestOutputHelper output, SharedConnectionFixture? connection = null, InProcServerFixture? server = null)
2837
{
2938
Output = output;
3039
Output.WriteFrameworkVersion();
3140
Writer = new TextWriterOutputHelper(output);
32-
_fixture = fixture;
41+
_sharedConnectionFixture = connection;
42+
_inProcServerFixture = server;
3343
ClearAmbientFailures();
3444
}
3545

46+
protected TestBase(ITestOutputHelper output, InProcServerFixture fixture) : this(output, null, fixture)
47+
{
48+
}
49+
3650
/// <summary>
3751
/// Useful to temporarily get extra worker threads for an otherwise synchronous test case which will 'block' the thread,
3852
/// on a synchronous API like <see cref="Task.Wait"/> or <see cref="Task.Result"/>.
@@ -85,7 +99,7 @@ protected static void CollectGarbage()
8599
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "Trust me yo")]
86100
public void Dispose()
87101
{
88-
_fixture?.Teardown(Writer);
102+
_sharedConnectionFixture?.Teardown(Writer);
89103
Teardown();
90104
Writer.Dispose();
91105
GC.SuppressFinalize(this);
@@ -226,6 +240,8 @@ protected static IServer GetAnyPrimary(IConnectionMultiplexer muxer)
226240

227241
internal virtual bool HighIntegrity => false;
228242

243+
internal virtual Tunnel? Tunnel => _inProcServerFixture?.Tunnel;
244+
229245
internal virtual IInternalConnectionMultiplexer Create(
230246
string? clientName = null,
231247
int? syncTimeout = null,
@@ -262,17 +278,18 @@ internal virtual IInternalConnectionMultiplexer Create(
262278

263279
// Share a connection if instructed to and we can - many specifics mean no sharing
264280
bool highIntegrity = HighIntegrity;
265-
if (shared && expectedFailCount == 0
266-
&& _fixture != null && _fixture.IsEnabled
281+
var tunnel = Tunnel;
282+
if (tunnel is null && shared && expectedFailCount == 0
283+
&& _sharedConnectionFixture != null && _sharedConnectionFixture.IsEnabled
267284
&& GetConfiguration() == GetDefaultConfiguration()
268285
&& CanShare(allowAdmin, password, tieBreaker, fail, disabledCommands, enabledCommands, channelPrefix, proxy, configuration, defaultDatabase, backlogPolicy, highIntegrity))
269286
{
270287
configuration = GetConfiguration();
271-
var fixtureConn = _fixture.GetConnection(this, protocol.Value, caller: caller);
288+
var fixtureConn = _sharedConnectionFixture.GetConnection(this, protocol.Value, caller: caller);
272289
// Only return if we match
273290
TestBase.ThrowIfIncorrectProtocol(fixtureConn, protocol);
274291

275-
if (configuration == _fixture.Configuration)
292+
if (configuration == _sharedConnectionFixture.Configuration)
276293
{
277294
TestBase.ThrowIfBelowMinVersion(fixtureConn, require);
278295
return fixtureConn;
@@ -303,6 +320,7 @@ internal virtual IInternalConnectionMultiplexer Create(
303320
backlogPolicy,
304321
protocol,
305322
highIntegrity,
323+
tunnel,
306324
caller);
307325

308326
TestBase.ThrowIfIncorrectProtocol(conn, protocol);
@@ -392,6 +410,7 @@ public static ConnectionMultiplexer CreateDefault(
392410
BacklogPolicy? backlogPolicy = null,
393411
RedisProtocol? protocol = null,
394412
bool highIntegrity = false,
413+
Tunnel? tunnel = null,
395414
[CallerMemberName] string caller = "")
396415
{
397416
StringWriter? localLog = null;
@@ -413,6 +432,7 @@ public static ConnectionMultiplexer CreateDefault(
413432
syncTimeout = int.MaxValue;
414433
}
415434

435+
config.Tunnel = tunnel;
416436
if (channelPrefix is not null) config.ChannelPrefix = RedisChannel.Literal(channelPrefix);
417437
if (tieBreaker is not null) config.TieBreaker = tieBreaker;
418438
if (password is not null) config.Password = string.IsNullOrEmpty(password) ? null : password;

toys/StackExchange.Redis.Server/RedisServer.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,22 @@ protected virtual bool Rename(int database, in RedisKey oldKey, in RedisKey newK
318318
return true;
319319
}
320320

321+
[RedisCommand(4)]
322+
protected virtual TypedRedisValue SetEx(RedisClient client, in RedisRequest request)
323+
{
324+
RedisKey key = request.GetKey(1);
325+
int seconds = request.GetInt32(2);
326+
var value = request.GetValue(3);
327+
SetEx(client.Database, key, seconds, value);
328+
return TypedRedisValue.OK;
329+
}
330+
331+
protected virtual void SetEx(int database, in RedisKey key, int seconds, in RedisValue value)
332+
{
333+
Set(database, key, value);
334+
Expire(database, key, TimeSpan.FromSeconds(seconds));
335+
}
336+
321337
[RedisCommand(3, "client", "setname", LockFree = true)]
322338
protected virtual TypedRedisValue ClientSetname(RedisClient client, in RedisRequest request)
323339
{

0 commit comments

Comments
 (0)