Commit 2a5c4f7a authored by Marc Gravell's avatar Marc Gravell

optional reusable connection fixture for sharing a muxer between tests

parent 5e6f36d2
......@@ -18,7 +18,7 @@ namespace StackExchange.Redis
/// <summary>
/// Represents an inter-related group of connections to redis servers
/// </summary>
public sealed partial class ConnectionMultiplexer : IConnectionMultiplexer, IDisposable
public sealed partial class ConnectionMultiplexer : IInternalConnectionMultiplexer // implies : IConnectionMultiplexer and : IDisposable
{
private const string timeoutHelpLink = "https://stackexchange.github.io/StackExchange.Redis/Timeouts";
......@@ -36,10 +36,23 @@ public sealed partial class ConnectionMultiplexer : IConnectionMultiplexer, IDis
}
#endif
bool IInternalConnectionMultiplexer.AllowConnect
{
get => AllowConnect;
set => AllowConnect = value;
}
bool IInternalConnectionMultiplexer.IgnoreConnect
{
get => IgnoreConnect;
set => IgnoreConnect = value;
}
/// <summary>
/// For debugging: when not enabled, servers cannot connect
/// </summary>
internal volatile bool AllowConnect = true;
/// <summary>
/// For debugging: when not enabled, end-connect is silently ignored (to simulate a long-running connect)
/// </summary>
......@@ -903,6 +916,8 @@ private static ConnectionMultiplexer ConnectImpl(object configuration, TextWrite
private string failureMessage;
private readonly Hashtable servers = new Hashtable();
private volatile ServerSnapshot _serverSnapshot = ServerSnapshot.Empty;
ReadOnlySpan<ServerEndPoint> IInternalConnectionMultiplexer.GetServerSnapshot() => GetServerSnapshot();
internal ReadOnlySpan<ServerEndPoint> GetServerSnapshot() => _serverSnapshot.Span;
private sealed class ServerSnapshot
{
......
......@@ -6,10 +6,19 @@
namespace StackExchange.Redis
{
internal interface IInternalConnectionMultiplexer : IConnectionMultiplexer
{
bool AllowConnect { get; set; }
bool IgnoreConnect { get; set; }
ReadOnlySpan<ServerEndPoint> GetServerSnapshot();
}
/// <summary>
/// Represents the abstract multiplexer API
/// </summary>
public interface IConnectionMultiplexer
public interface IConnectionMultiplexer : IDisposable
{
/// <summary>
/// Gets the client-name that will be used on all new connections
......@@ -220,11 +229,6 @@ public interface IConnectionMultiplexer
/// <param name="allowCommandsToComplete">Whether to allow in-queue commadns to complete first.</param>
Task CloseAsync(bool allowCommandsToComplete = true);
/// <summary>
/// Release all resources associated with this object
/// </summary>
void Dispose();
/// <summary>
/// Obtains the log of unusual busy patterns
/// </summary>
......@@ -254,5 +258,12 @@ public interface IConnectionMultiplexer
/// </summary>
/// <param name="key">The key to get a the slot for.</param>
int GetHashSlot(RedisKey key);
/// <summary>
/// Write the configuration of all servers to an output stream
/// </summary>
/// <param name="destination">The destination stream to write the export to.</param>
/// <param name="options">The options to use for this export.</param>
void ExportConfiguration(Stream destination, ExportOptions options = ExportOptions.All);
}
}
......@@ -3,9 +3,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class AdhocTests : TestBase
{
public AdhocTests(ITestOutputHelper output) : base (output) { }
public AdhocTests(ITestOutputHelper output, SharedConnectionFixture fixture) : base (output, fixture) { }
[Fact]
public void TestAdhocCommandsAPI()
......
......@@ -16,7 +16,7 @@ public async Task ParallelTransactionsWithConditions()
{
const int Muxers = 4, Workers = 20, PerThread = 250;
var muxers = new ConnectionMultiplexer[Muxers];
var muxers = new IConnectionMultiplexer[Muxers];
try
{
for (int i = 0; i < Muxers; i++)
......
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using StackExchange.Redis.KeyspaceIsolation;
using Xunit;
using Xunit.Abstractions;
using System.Diagnostics;
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class BasicOpsTests : TestBase
{
public BasicOpsTests(ITestOutputHelper output) : base (output) { }
public BasicOpsTests(ITestOutputHelper output, SharedConnectionFixture fixture) : base (output, fixture) { }
[Fact]
public async Task PingOnce()
......@@ -35,7 +36,7 @@ public void RapidDispose()
for (int i = 0; i < 10; i++)
{
using (var secondary = Create(fail: true))
using (var secondary = Create(fail: true, shared: false))
{
secondary.GetDatabase().StringIncrement(key, flags: CommandFlags.FireAndForget);
}
......@@ -398,6 +399,33 @@ private void Incr(IDatabase database, RedisKey key, int delta, ref int total)
total += delta;
}
[Fact]
public void ShouldUseSharedMuxer()
{
if (SharedFixtureAvailable)
{
using (var a = Create())
{
Assert.IsNotType<ConnectionMultiplexer>(a);
using (var b = Create())
{
Assert.Same(a, b);
}
}
}
else
{
using (var a = Create())
{
Assert.IsType<ConnectionMultiplexer>(a);
using (var b = Create())
{
Assert.NotSame(a, b);
}
}
}
}
[Fact]
public async Task Delete()
{
......
......@@ -6,9 +6,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class Batches : TestBase
{
public Batches(ITestOutputHelper output) : base(output) { }
public Batches(ITestOutputHelper output, SharedConnectionFixture fixture) : base(output, fixture) { }
[Fact]
public void TestBatchNotSent()
......
......@@ -3,9 +3,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class Bits : TestBase
{
public Bits(ITestOutputHelper output) : base (output) { }
public Bits(ITestOutputHelper output, SharedConnectionFixture fixture) : base (output, fixture) { }
[Fact]
public void BasicOps()
......
......@@ -4,9 +4,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class Constraints : TestBase
{
public Constraints(ITestOutputHelper output) : base(output) { }
public Constraints(ITestOutputHelper output, SharedConnectionFixture fixture) : base(output, fixture) { }
[Fact]
public void ValueEquals()
......
......@@ -4,9 +4,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class Databases : TestBase
{
public Databases(ITestOutputHelper output) : base (output) { }
public Databases(ITestOutputHelper output, SharedConnectionFixture fixture) : base (output, fixture) { }
[Fact]
public async Task CountKeys()
......
......@@ -5,9 +5,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class ExecuteTests : TestBase
{
public ExecuteTests(ITestOutputHelper output) : base(output) { }
public ExecuteTests(ITestOutputHelper output, SharedConnectionFixture fixture) : base(output, fixture) { }
[Fact]
public async Task DBExecute()
......
......@@ -5,9 +5,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class Expiry : TestBase
{
public Expiry(ITestOutputHelper output) : base (output) { }
public Expiry(ITestOutputHelper output, SharedConnectionFixture fixture) : base (output, fixture) { }
private static string[] GetMap(bool disablePTimes) => disablePTimes ? (new[] { "pexpire", "pexpireat", "pttl" }) : null;
......
......@@ -199,8 +199,8 @@ public async Task SubscriptionsSurviveMasterSwitchAsync()
Skip.Inconclusive("TODO: Fix race in broadcast reconfig a zero latency.");
}
using (var a = Create(allowAdmin: true))
using (var b = Create(allowAdmin: true))
using (var a = Create(allowAdmin: true, shared: false))
using (var b = Create(allowAdmin: true, shared: false))
{
RedisChannel channel = Me();
var subA = a.GetSubscriber();
......
......@@ -5,9 +5,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class FloatingPoint : TestBase
{
public FloatingPoint(ITestOutputHelper output) : base (output) { }
public FloatingPoint(ITestOutputHelper output, SharedConnectionFixture fixture) : base (output, fixture) { }
private static bool Within(double x, double y, double delta)
{
......
......@@ -5,9 +5,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class GeoTests : TestBase
{
public GeoTests(ITestOutputHelper output) : base (output) { }
public GeoTests(ITestOutputHelper output, SharedConnectionFixture fixture) : base (output, fixture) { }
public static GeoEntry
palermo = new GeoEntry(13.361389, 38.115556, "Palermo"),
......
......@@ -9,9 +9,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class Hashes : TestBase // https://redis.io/commands#hash
{
public Hashes(ITestOutputHelper output) : base(output) { }
public Hashes(ITestOutputHelper output, SharedConnectionFixture fixture) : base(output, fixture) { }
[Fact]
public async Task TestIncrBy()
......
......@@ -23,7 +23,7 @@ public static void IfNoConfig(string prop, List<string> values)
}
}
public static void IfMissingFeature(ConnectionMultiplexer conn, string feature, Func<RedisFeatures, bool> check)
public static void IfMissingFeature(IConnectionMultiplexer conn, string feature, Func<RedisFeatures, bool> check)
{
var features = conn.GetServer(conn.GetEndPoints()[0]).Features;
if (!check(features))
......@@ -35,7 +35,7 @@ public static void IfMissingFeature(ConnectionMultiplexer conn, string feature,
}
}
internal static void IfMissingDatabase(ConnectionMultiplexer conn, int dbId)
internal static void IfMissingDatabase(IConnectionMultiplexer conn, int dbId)
{
var dbCount = conn.GetServer(conn.GetEndPoints()[0]).DatabaseCount;
if (dbId >= dbCount) throw new SkipTestException($"Database '{dbId}' is not supported on this server.");
......
......@@ -12,7 +12,7 @@ public static class TestConfig
public static Config Current { get; }
private static int _db = 17;
public static int GetDedicatedDB(ConnectionMultiplexer conn = null)
public static int GetDedicatedDB(IConnectionMultiplexer conn = null)
{
int db = Interlocked.Increment(ref _db);
if (conn != null) Skip.IfMissingDatabase(conn, db);
......
......@@ -3,9 +3,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class HyperLogLog : TestBase
{
public HyperLogLog(ITestOutputHelper output) : base (output) { }
public HyperLogLog(ITestOutputHelper output, SharedConnectionFixture fixture) : base (output, fixture) { }
[Fact]
public void SingleKeyLength()
......
......@@ -7,9 +7,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class Keys : TestBase
{
public Keys(ITestOutputHelper output) : base (output) { }
public Keys(ITestOutputHelper output, SharedConnectionFixture fixture) : base (output, fixture) { }
[Fact]
public void TestScan()
......
......@@ -3,9 +3,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class Lex : TestBase
{
public Lex(ITestOutputHelper output) : base(output) { }
public Lex(ITestOutputHelper output, SharedConnectionFixture fixture) : base(output, fixture) { }
[Fact]
public void QueryRangeAndLengthByLex()
......
......@@ -4,9 +4,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class Lists : TestBase
{
public Lists(ITestOutputHelper output) : base(output) { }
public Lists(ITestOutputHelper output, SharedConnectionFixture fixture) : base(output, fixture) { }
[Fact]
public void Ranges()
......
......@@ -76,7 +76,7 @@ public void TestOpCountByVersionLocal_UpLevel()
}
}
private void TestLockOpCountByVersion(ConnectionMultiplexer conn, int expectedOps, bool existFirst)
private void TestLockOpCountByVersion(IConnectionMultiplexer conn, int expectedOps, bool existFirst)
{
const int LockDuration = 30;
RedisKey Key = Me();
......@@ -103,7 +103,7 @@ private void TestLockOpCountByVersion(ConnectionMultiplexer conn, int expectedOp
// note we get a ping from GetCounters
}
private ConnectionMultiplexer Create(TestMode mode)
private IConnectionMultiplexer Create(TestMode mode)
{
switch (mode)
{
......
......@@ -4,9 +4,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class MultiAdd : TestBase
{
public MultiAdd(ITestOutputHelper output) : base(output) { }
public MultiAdd(ITestOutputHelper output, SharedConnectionFixture fixture) : base(output, fixture) { }
[Fact]
public void AddSortedSetEveryWay()
......
......@@ -7,9 +7,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class PreserveOrder : TestBase
{
public PreserveOrder(ITestOutputHelper output) : base (output) { }
public PreserveOrder(ITestOutputHelper output, SharedConnectionFixture fixture) : base (output, fixture) { }
[Fact]
public void Execute()
......
......@@ -73,7 +73,7 @@ public void Simple()
}
}
private static void AssertProfiledCommandValues(IProfiledCommand command, ConnectionMultiplexer conn, int dbId)
private static void AssertProfiledCommandValues(IProfiledCommand command, IConnectionMultiplexer conn, int dbId)
{
Assert.Equal(dbId, command.Db);
Assert.Equal(conn.GetEndPoints()[0], command.EndPoint);
......@@ -275,7 +275,7 @@ public void ProfilingMD_Ex1()
{
using (var c = Create())
{
ConnectionMultiplexer conn = c;
IConnectionMultiplexer conn = c;
var session = new ProfilingSession();
var prefix = Me();
......@@ -317,7 +317,7 @@ public void ProfilingMD_Ex2()
{
using (var c = Create())
{
ConnectionMultiplexer conn = c;
IConnectionMultiplexer conn = c;
var profiler = new PerThreadProfiler();
var prefix = Me();
......@@ -362,7 +362,7 @@ public async Task ProfilingMD_Ex2_Async()
{
using (var c = Create())
{
ConnectionMultiplexer conn = c;
IConnectionMultiplexer conn = c;
var profiler = new AsyncLocalProfiler();
var prefix = Me();
......
......@@ -10,9 +10,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class PubSub : TestBase
{
public PubSub(ITestOutputHelper output) : base(output) { }
public PubSub(ITestOutputHelper output, SharedConnectionFixture fixture) : base(output, fixture) { }
[Fact]
public async Task ExplicitPublishMode()
......@@ -172,7 +173,7 @@ public async Task TestBasicPubSubFireAndForget()
}
}
private static async Task PingAsync(ConnectionMultiplexer muxer, IServer pub, ISubscriber sub, int times = 1)
private static async Task PingAsync(IConnectionMultiplexer muxer, IServer pub, ISubscriber sub, int times = 1)
{
while (times-- > 0)
{
......@@ -558,8 +559,8 @@ public async Task PubSubGetAllCorrectOrder_OnMessage_Async()
public async Task TestPublishWithSubscribers()
{
var channel = Me();
using (var muxerA = Create())
using (var muxerB = Create())
using (var muxerA = Create(shared: false))
using (var muxerB = Create(shared: false))
using (var conn = Create())
{
var listenA = muxerA.GetSubscriber();
......@@ -578,8 +579,8 @@ public async Task TestPublishWithSubscribers()
public async Task TestMultipleSubscribersGetMessage()
{
var channel = Me();
using (var muxerA = Create())
using (var muxerB = Create())
using (var muxerA = Create(shared: false))
using (var muxerB = Create(shared: false))
using (var conn = Create())
{
var listenA = muxerA.GetSubscriber();
......
......@@ -4,9 +4,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class PubSubCommand : TestBase
{
public PubSubCommand(ITestOutputHelper output) : base (output) { }
public PubSubCommand(ITestOutputHelper output, SharedConnectionFixture fixture) : base (output, fixture) { }
[Fact]
public void SubscriberCount()
......
......@@ -6,9 +6,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class Scans : TestBase
{
public Scans(ITestOutputHelper output) : base (output) { }
public Scans(ITestOutputHelper output, SharedConnectionFixture fixture) : base (output, fixture) { }
[Theory]
[InlineData(true)]
......@@ -339,7 +340,7 @@ public void HashScanThresholds()
}
}
private bool GotCursors(ConnectionMultiplexer conn, RedisKey key, int count)
private bool GotCursors(IConnectionMultiplexer conn, RedisKey key, int count)
{
var db = conn.GetDatabase();
db.KeyDelete(key, CommandFlags.FireAndForget);
......
......@@ -8,11 +8,12 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class Scripting : TestBase
{
public Scripting(ITestOutputHelper output) : base (output) { }
public Scripting(ITestOutputHelper output, SharedConnectionFixture fixture) : base (output, fixture) { }
private ConnectionMultiplexer GetScriptConn(bool allowAdmin = false)
private IConnectionMultiplexer GetScriptConn(bool allowAdmin = false)
{
int syncTimeout = 5000;
if (Debugger.IsAttached) syncTimeout = 500000;
......@@ -596,7 +597,7 @@ public void LuaScriptWithKeys()
var p = new { key = (RedisKey)key, value = 123 };
script.Evaluate(db, p, flags: CommandFlags.FireAndForget);
script.Evaluate(db, p);
var val = db.StringGet(key);
Assert.Equal(123, (int)val);
......@@ -804,7 +805,7 @@ public void IServerLuaScriptConvenienceMethods()
var prepared = server.ScriptLoad(script);
db.ScriptEvaluate(prepared, new { key = (RedisKey)key, value = "value3" }, flags: CommandFlags.FireAndForget);
db.ScriptEvaluate(prepared, new { key = (RedisKey)key, value = "value3" });
var val = db.StringGet(key);
Assert.Equal("value3", val);
}
......@@ -842,7 +843,7 @@ public void LuaScriptWithWrappedDatabase()
db.KeyDelete(key, CommandFlags.FireAndForget);
var prepared = LuaScript.Prepare(Script);
wrappedDb.ScriptEvaluate(prepared, new { key = (RedisKey)key, value = 123 }, flags: CommandFlags.FireAndForget);
wrappedDb.ScriptEvaluate(prepared, new { key = (RedisKey)key, value = 123 });
var val1 = wrappedDb.StringGet(key);
Assert.Equal(123, (int)val1);
......
......@@ -6,9 +6,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class Sets : TestBase
{
public Sets(ITestOutputHelper output) : base (output) { }
public Sets(ITestOutputHelper output, SharedConnectionFixture fixture) : base (output, fixture) { }
[Fact]
public void SScan()
......
This diff is collapsed.
......@@ -6,9 +6,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class Streams : TestBase
{
public Streams(ITestOutputHelper output) : base(output) { }
public Streams(ITestOutputHelper output, SharedConnectionFixture fixture) : base(output, fixture) { }
[Fact]
public void IsStreamType()
......
......@@ -7,9 +7,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class Strings : TestBase // https://redis.io/commands#string
{
public Strings(ITestOutputHelper output) : base(output) { }
public Strings(ITestOutputHelper output, SharedConnectionFixture fixture) : base(output, fixture) { }
[Fact]
public async Task Append()
......
This diff is collapsed.
......@@ -10,9 +10,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class Transactions : TestBase
{
public Transactions(ITestOutputHelper output) : base(output) { }
public Transactions(ITestOutputHelper output, SharedConnectionFixture fixture) : base(output, fixture) { }
[Fact]
public void BasicEmptyTran()
......
......@@ -5,9 +5,10 @@
namespace StackExchange.Redis.Tests
{
[Collection(SharedConnectionFixture.Key)]
public class WithKeyPrefixTests : TestBase
{
public WithKeyPrefixTests(ITestOutputHelper output) : base(output) { }
public WithKeyPrefixTests(ITestOutputHelper output, SharedConnectionFixture fixture) : base(output, fixture) { }
[Fact]
public void BlankPrefixYieldsSame_Bytes()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment