diff --git a/Directory.Packages.props b/Directory.Packages.props index 0719a40ed8..60462d5b1b 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -9,6 +9,7 @@ + diff --git a/benchmark/BDN.benchmark/BDN.benchmark.csproj b/benchmark/BDN.benchmark/BDN.benchmark.csproj index 71c1961eee..99fc55eafe 100644 --- a/benchmark/BDN.benchmark/BDN.benchmark.csproj +++ b/benchmark/BDN.benchmark/BDN.benchmark.csproj @@ -29,4 +29,8 @@ + + + + diff --git a/benchmark/BDN.benchmark/Cluster/ClusterContext.cs b/benchmark/BDN.benchmark/Cluster/ClusterContext.cs index 631a7dda90..ffd1089489 100644 --- a/benchmark/BDN.benchmark/Cluster/ClusterContext.cs +++ b/benchmark/BDN.benchmark/Cluster/ClusterContext.cs @@ -10,9 +10,9 @@ namespace BDN.benchmark.Cluster { - unsafe class ClusterContext + class ClusterContext { - EmbeddedRespServer server; + GarnetEmbeddedApplication server; RespServerSession session; readonly BenchUtils benchUtils = new(); readonly int port = 7000; @@ -22,9 +22,11 @@ unsafe class ClusterContext public Request[] singleMGetMSet; public Request singleCTXNSET; - public void Dispose() + public async Task Dispose() { session.Dispose(); + await server.StopAsync(); + server.Dispose(); server.Dispose(); } @@ -39,12 +41,17 @@ public void SetupSingleInstance(bool disableSlotVerification = false) }; if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) opt.CheckpointDir = "/tmp"; - server = new EmbeddedRespServer(opt); + + var builder = GarnetEmbeddedApplication.CreateHostBuilder([], opt); + + server = builder.Build(); + session = server.GetRespSession(); + _ = server.Register.NewTransactionProc(CustomTxnSet.CommandName, () => new CustomTxnSet(), new RespCommandsInfo { Arity = CustomTxnSet.Arity }); } - public void AddSlotRange(List<(int, int)> slotRanges) + public unsafe void AddSlotRange(List<(int, int)> slotRanges) { foreach (var slotRange in slotRanges) { @@ -56,7 +63,7 @@ public void AddSlotRange(List<(int, int)> slotRanges) } } - public void CreateGetSet(int keySize = 8, int valueSize = 32, int batchSize = 100) + public unsafe void CreateGetSet(int keySize = 8, int valueSize = 32, int batchSize = 100) { var pairs = new (byte[], byte[])[batchSize]; for (var i = 0; i < batchSize; i++) @@ -93,7 +100,7 @@ public void CreateGetSet(int keySize = 8, int valueSize = 32, int batchSize = 10 singleGetSet = [getReq, setReq]; } - public void CreateMGetMSet(int keySize = 8, int valueSize = 32, int batchSize = 100) + public unsafe void CreateMGetMSet(int keySize = 8, int valueSize = 32, int batchSize = 100) { var pairs = new (byte[], byte[])[batchSize]; for (var i = 0; i < batchSize; i++) @@ -134,7 +141,7 @@ public void CreateMGetMSet(int keySize = 8, int valueSize = 32, int batchSize = singleMGetMSet = [mGetReq, mSetReq]; } - public void CreateCTXNSET(int keySize = 8, int batchSize = 100) + public unsafe void CreateCTXNSET(int keySize = 8, int batchSize = 100) { var keys = new byte[8][]; for (var i = 0; i < 8; i++) @@ -163,7 +170,7 @@ public void CreateCTXNSET(int keySize = 8, int batchSize = 100) singleCTXNSET = ctxnsetReq; } - public void Consume(byte* ptr, int length) + public unsafe void Consume(byte* ptr, int length) => session.TryConsumeMessages(ptr, length); } diff --git a/benchmark/BDN.benchmark/Embedded/EmbeddedRespServer.cs b/benchmark/BDN.benchmark/Embedded/EmbeddedRespServer.cs deleted file mode 100644 index bae520f373..0000000000 --- a/benchmark/BDN.benchmark/Embedded/EmbeddedRespServer.cs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -using Garnet; -using Garnet.common; -using Garnet.server; -using Microsoft.Extensions.Logging; -using Tsavorite.core; - -namespace Embedded.server -{ - /// - /// Implements an embedded Garnet RESP server - /// - internal sealed class EmbeddedRespServer : GarnetServer - { - readonly GarnetServerEmbedded garnetServerEmbedded; - readonly SubscribeBroker> subscribeBroker; - - /// - /// Creates an EmbeddedRespServer instance - /// - /// Server options to configure the base GarnetServer instance - /// Logger factory to configure the base GarnetServer instance - /// Server network - public EmbeddedRespServer(GarnetServerOptions opts, ILoggerFactory loggerFactory = null, GarnetServerEmbedded server = null) : base(opts, loggerFactory, server) - { - this.garnetServerEmbedded = server; - this.subscribeBroker = opts.DisablePubSub ? null : - new SubscribeBroker>( - new SpanByteKeySerializer(), - null, - opts.PubSubPageSizeBytes(), - opts.SubscriberRefreshFrequencyMs, - true); - } - - /// - /// Dispose server - /// - public new void Dispose() => base.Dispose(); - - public StoreWrapper StoreWrapper => storeWrapper; - - /// - /// Return a direct RESP session to this server - /// - /// A new RESP server session - internal RespServerSession GetRespSession() - { - return new RespServerSession(0, new EmbeddedNetworkSender(), storeWrapper, subscribeBroker: subscribeBroker, null, true); - } - - internal EmbeddedNetworkHandler GetNetworkHandler() - { - return garnetServerEmbedded.CreateNetworkHandler(); - } - } -} \ No newline at end of file diff --git a/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplication.cs b/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplication.cs new file mode 100644 index 0000000000..dbecf59b5a --- /dev/null +++ b/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplication.cs @@ -0,0 +1,77 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Garnet; +using Garnet.common; +using Garnet.server; +using Microsoft.Extensions.DependencyInjection; +using Tsavorite.core; + +namespace Embedded.server; + +internal sealed class GarnetEmbeddedApplication +{ + public RegisterApi Register => app.Register; + + readonly StoreWrapper store; + readonly SubscribeBroker> subscriberBroker; + readonly GarnetApplication app; + + public GarnetEmbeddedApplication(GarnetApplication app) + { + this.app = app; + this.store = app.Services.GetRequiredService(); + this.subscriberBroker = + app.Services.GetRequiredService>>(); + } + + public static GarnetEmbeddedApplicationBuilder CreateHostBuilder(string[] args, GarnetServerOptions options) + { + return new(new GarnetApplicationOptions + { + Args = args, + }, options); + } + + public async Task StopAsync(CancellationToken cancellationToken = default) + { + await app.StopAsync(cancellationToken); + } + + /// + /// Dispose server + /// + public void Dispose() => app.Dispose(); + + public StoreWrapper StoreWrapper => store; + + /// + /// Return a direct RESP session to this server + /// + /// A new RESP server session + internal RespServerSession GetRespSession() + { + return new RespServerSession(0, + new EmbeddedNetworkSender(), + store, + subscribeBroker: this.subscriberBroker, + null, + true); + } + + internal EmbeddedNetworkHandler GetNetworkHandler() + { + var server = app.Services + .GetServices() + .OfType() + .FirstOrDefault(); + + Console.WriteLine(server); + + return server?.CreateNetworkHandler(); + } +} \ No newline at end of file diff --git a/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplicationBuilder.cs b/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplicationBuilder.cs new file mode 100644 index 0000000000..527809b17a --- /dev/null +++ b/benchmark/BDN.benchmark/Embedded/GarnetEmbeddedApplicationBuilder.cs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using System.Linq; +using Garnet; +using Garnet.server; +using Microsoft.Extensions.DependencyInjection; + +namespace Embedded.server; + +internal class GarnetEmbeddedApplicationBuilder : GarnetApplicationBuilder +{ + internal GarnetEmbeddedApplicationBuilder(GarnetApplicationOptions options, GarnetServerOptions garnetServerOptions) + : base(options, garnetServerOptions) + { + } + + public new GarnetEmbeddedApplication Build() + { + { + var serviceDescriptor = base.Services + .FirstOrDefault(descriptor => descriptor.ServiceType == typeof(StoreWrapper)); + + base.Services.Remove(serviceDescriptor); + } + + { + var serviceDescriptor = base.Services + .FirstOrDefault(descriptor => descriptor.ServiceType == typeof(IGarnetServer)); + + base.Services.Remove(serviceDescriptor); + + base.Services.AddSingleton(); + } + + var app = base.Build(); + + return new GarnetEmbeddedApplication(app); + } +} \ No newline at end of file diff --git a/benchmark/BDN.benchmark/Embedded/GarnetServerEmbedded.cs b/benchmark/BDN.benchmark/Embedded/GarnetServerEmbedded.cs index 63fe7d90ec..99687f0109 100644 --- a/benchmark/BDN.benchmark/Embedded/GarnetServerEmbedded.cs +++ b/benchmark/BDN.benchmark/Embedded/GarnetServerEmbedded.cs @@ -9,93 +9,92 @@ using Garnet.server; using Microsoft.Extensions.Logging; -namespace Embedded.server +namespace Embedded.server; + +internal class GarnetServerEmbedded : GarnetServerBase, IServerHook { - internal class GarnetServerEmbedded : GarnetServerBase, IServerHook + public GarnetServerEmbedded() : base("0.0.0.0", 0, 1 << 10) { - public GarnetServerEmbedded() : base("0.0.0.0", 0, 1 << 10) - { - } + } - public EmbeddedNetworkHandler CreateNetworkHandler(SslClientAuthenticationOptions tlsOptions = null, string remoteEndpointName = null) - { - var networkSender = new EmbeddedNetworkSender(); - var networkSettings = new NetworkBufferSettings(); - var networkPool = networkSettings.CreateBufferPool(); - EmbeddedNetworkHandler handler = null; + public EmbeddedNetworkHandler CreateNetworkHandler(SslClientAuthenticationOptions tlsOptions = null, string remoteEndpointName = null) + { + var networkSender = new EmbeddedNetworkSender(); + var networkSettings = new NetworkBufferSettings(); + var networkPool = networkSettings.CreateBufferPool(); + EmbeddedNetworkHandler handler = null; - if (activeHandlerCount >= 0) + if (activeHandlerCount >= 0) + { + var currentActiveHandlerCount = Interlocked.Increment(ref activeHandlerCount); + if (currentActiveHandlerCount > 0) { - var currentActiveHandlerCount = Interlocked.Increment(ref activeHandlerCount); - if (currentActiveHandlerCount > 0) + try { - try - { - handler = new EmbeddedNetworkHandler(this, networkSender, networkSettings, networkPool, tlsOptions != null); - if (!activeHandlers.TryAdd(handler, default)) - throw new Exception("Unable to add handler to dictionary"); + handler = new EmbeddedNetworkHandler(this, networkSender, networkSettings, networkPool, tlsOptions != null); + if (!activeHandlers.TryAdd(handler, default)) + throw new Exception("Unable to add handler to dictionary"); - handler.Start(tlsOptions, remoteEndpointName); - incr_conn_recv(); - return handler; - } - catch (Exception ex) - { - logger?.LogError(ex, "Error starting network handler"); - Interlocked.Decrement(ref activeHandlerCount); - handler?.Dispose(); - } + handler.Start(tlsOptions, remoteEndpointName); + incr_conn_recv(); + return handler; } - else + catch (Exception ex) { + logger?.LogError(ex, "Error starting network handler"); Interlocked.Decrement(ref activeHandlerCount); + handler?.Dispose(); } } - return handler; - } - - public void DisposeMessageConsumer(INetworkHandler session) - { - if (activeHandlers.TryRemove(session, out _)) + else { Interlocked.Decrement(ref activeHandlerCount); - incr_conn_disp(); - try - { - session.Session?.Dispose(); - } - catch (Exception ex) - { - logger?.LogError(ex, "Error disposing RespServerSession"); - } } } + return handler; + } - public override void Start() + public void DisposeMessageConsumer(INetworkHandler session) + { + if (activeHandlers.TryRemove(session, out _)) { + Interlocked.Decrement(ref activeHandlerCount); + incr_conn_disp(); + try + { + session.Session?.Dispose(); + } + catch (Exception ex) + { + logger?.LogError(ex, "Error disposing RespServerSession"); + } } + } - public bool TryCreateMessageConsumer(Span bytes, INetworkSender networkSender, out IMessageConsumer session) - { - session = null; - - // We need at least 4 bytes to determine session - if (bytes.Length < 4) - return false; + public override void Start() + { + } - WireFormat protocol = WireFormat.ASCII; + public bool TryCreateMessageConsumer(Span bytes, INetworkSender networkSender, out IMessageConsumer session) + { + session = null; - if (!GetSessionProviders().TryGetValue(protocol, out var provider)) - { - var input = System.Text.Encoding.ASCII.GetString(bytes); - logger?.LogError("Cannot identify wire protocol {bytes}", input); - throw new Exception($"Unsupported incoming wire format {protocol} {input}"); - } + // We need at least 4 bytes to determine session + if (bytes.Length < 4) + return false; - if (!AddSession(protocol, ref provider, networkSender, out session)) - throw new Exception($"Unable to add session"); + WireFormat protocol = WireFormat.ASCII; - return true; + if (!GetSessionProviders().TryGetValue(protocol, out var provider)) + { + var input = System.Text.Encoding.ASCII.GetString(bytes); + logger?.LogError("Cannot identify wire protocol {bytes}", input); + throw new Exception($"Unsupported incoming wire format {protocol} {input}"); } + + if (!AddSession(protocol, ref provider, networkSender, out session)) + throw new Exception($"Unable to add session"); + + return true; } } \ No newline at end of file diff --git a/benchmark/BDN.benchmark/Lua/LuaRunnerOperations.cs b/benchmark/BDN.benchmark/Lua/LuaRunnerOperations.cs index a100249efe..e4431fe236 100644 --- a/benchmark/BDN.benchmark/Lua/LuaRunnerOperations.cs +++ b/benchmark/BDN.benchmark/Lua/LuaRunnerOperations.cs @@ -3,6 +3,7 @@ using BenchmarkDotNet.Attributes; using Embedded.server; +using Garnet; using Garnet.server; namespace BDN.benchmark.Lua @@ -11,7 +12,7 @@ namespace BDN.benchmark.Lua /// Benchmark for non-script running operations in LuaRunner /// [MemoryDiagnoser] - public unsafe class LuaRunnerOperations + public class LuaRunnerOperations { private const string SmallScript = "return nil"; @@ -147,7 +148,7 @@ public IEnumerable LuaParamsProvider() new(LuaMemoryManagementMode.Managed, true), ]; - private EmbeddedRespServer server; + private GarnetEmbeddedApplication server; private RespServerSession session; private LuaRunner paramsRunner; @@ -162,7 +163,14 @@ public void GlobalSetup() { opts = Params.CreateOptions(); - server = new EmbeddedRespServer(new GarnetServerOptions() { EnableLua = true, QuietMode = true, LuaOptions = opts }); + var builder = GarnetEmbeddedApplication.CreateHostBuilder([], new GarnetServerOptions + { + EnableLua = true, + QuietMode = true, + LuaOptions = opts + }); + + server = builder.Build(); session = server.GetRespSession(); diff --git a/benchmark/BDN.benchmark/Lua/LuaScriptCacheOperations.cs b/benchmark/BDN.benchmark/Lua/LuaScriptCacheOperations.cs index 430a92ca59..efda07487a 100644 --- a/benchmark/BDN.benchmark/Lua/LuaScriptCacheOperations.cs +++ b/benchmark/BDN.benchmark/Lua/LuaScriptCacheOperations.cs @@ -30,7 +30,7 @@ public IEnumerable LuaParamsProvider() new(LuaMemoryManagementMode.Managed, true), ]; - private EmbeddedRespServer server; + private GarnetEmbeddedApplication server; private StoreWrapper storeWrapper; private SessionScriptCache sessionScriptCache; private RespServerSession session; @@ -44,7 +44,11 @@ public void GlobalSetup() { var options = Params.CreateOptions(); - server = new EmbeddedRespServer(new GarnetServerOptions() { EnableLua = true, QuietMode = true, LuaOptions = options }); + var builder = GarnetEmbeddedApplication.CreateHostBuilder([], + new GarnetServerOptions() { EnableLua = true, QuietMode = true, LuaOptions = options }); + + server = builder.Build(); + storeWrapper = server.StoreWrapper; sessionScriptCache = new SessionScriptCache(storeWrapper, new GarnetNoAuthAuthenticator()); session = server.GetRespSession(); diff --git a/benchmark/BDN.benchmark/Network/NetworkBase.cs b/benchmark/BDN.benchmark/Network/NetworkBase.cs index c76820a350..d922555d82 100644 --- a/benchmark/BDN.benchmark/Network/NetworkBase.cs +++ b/benchmark/BDN.benchmark/Network/NetworkBase.cs @@ -32,7 +32,7 @@ public IEnumerable NetworkParamsProvider() /// in order to stress the network layer. /// const int batchSize = 1; - EmbeddedRespServer server; + GarnetEmbeddedApplication server; EmbeddedNetworkHandler networkHandler; /// @@ -47,7 +47,9 @@ public virtual void GlobalSetup() DisablePubSub = true, }; - server = new EmbeddedRespServer(opts, null, new GarnetServerEmbedded()); + var builder = GarnetEmbeddedApplication.CreateHostBuilder([], opts); + + server = builder.Build(); networkHandler = server.GetNetworkHandler(); // Send a PING message to warm up the session diff --git a/benchmark/BDN.benchmark/Operations/OperationsBase.cs b/benchmark/BDN.benchmark/Operations/OperationsBase.cs index 16be016871..4f79511e75 100644 --- a/benchmark/BDN.benchmark/Operations/OperationsBase.cs +++ b/benchmark/BDN.benchmark/Operations/OperationsBase.cs @@ -41,7 +41,7 @@ public IEnumerable OperationParamsProvider() /// 100 us = 1 Mops/sec /// internal const int batchSize = 100; - internal EmbeddedRespServer server; + internal GarnetEmbeddedApplication server; internal RespServerSession session; internal RespServerSession subscribeSession; @@ -79,7 +79,9 @@ public virtual void GlobalSetup() opts.AuthSettings = new AclAuthenticationPasswordSettings(aclFile); } - server = new EmbeddedRespServer(opts, null, new GarnetServerEmbedded()); + var builder = GarnetEmbeddedApplication.CreateHostBuilder([], opts); + + server = builder.Build(); session = server.GetRespSession(); } finally diff --git a/benchmark/BDN.benchmark/Operations/PubSubOperations.cs b/benchmark/BDN.benchmark/Operations/PubSubOperations.cs index a2414d8405..4b8d9f2e2c 100644 --- a/benchmark/BDN.benchmark/Operations/PubSubOperations.cs +++ b/benchmark/BDN.benchmark/Operations/PubSubOperations.cs @@ -27,7 +27,8 @@ public override void GlobalSetup() DisablePubSub = false, }; - server = new EmbeddedRespServer(opts, null, new GarnetServerEmbedded()); + var builder = GarnetEmbeddedApplication.CreateHostBuilder([], opts); + server = builder.Build(); session = server.GetRespSession(); subscribeSession = server.GetRespSession(); diff --git a/benchmark/BDN.benchmark/Operations/ScriptOperations.cs b/benchmark/BDN.benchmark/Operations/ScriptOperations.cs index b8298912eb..d04c59eaa0 100644 --- a/benchmark/BDN.benchmark/Operations/ScriptOperations.cs +++ b/benchmark/BDN.benchmark/Operations/ScriptOperations.cs @@ -187,7 +187,7 @@ public static IEnumerable LuaParamsProvider() /// 100 us = 1 Mops/sec /// internal const int batchSize = 100; - internal EmbeddedRespServer server; + internal GarnetEmbeddedApplication server; internal RespServerSession session; /// @@ -203,7 +203,8 @@ public void GlobalSetup() LuaOptions = Params.CreateOptions(), }; - server = new EmbeddedRespServer(opts); + var builder = GarnetEmbeddedApplication.CreateHostBuilder([], opts); + server = builder.Build(); session = server.GetRespSession(); diff --git a/hosting/Windows/Garnet.worker/Program.cs b/hosting/Windows/Garnet.worker/Program.cs index 8418da8671..854d7c4ab4 100644 --- a/hosting/Windows/Garnet.worker/Program.cs +++ b/hosting/Windows/Garnet.worker/Program.cs @@ -5,19 +5,12 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -class Program -{ - static void Main(string[] args) - { - var builder = Host.CreateApplicationBuilder(args); - builder.Services.AddHostedService(_ => new Worker(args)); +var builder = GarnetApplication.CreateHostBuilder(args); - builder.Services.AddWindowsService(options => - { - options.ServiceName = "Microsoft Garnet Server"; - }); +builder.Services.AddWindowsService(options => +{ + options.ServiceName = "Microsoft Garnet Server"; +}); - var host = builder.Build(); - host.Run(); - } -} \ No newline at end of file +var app = builder.Build(); +app.Run(); \ No newline at end of file diff --git a/hosting/Windows/Garnet.worker/Worker.cs b/hosting/Windows/Garnet.worker/Worker.cs deleted file mode 100644 index d69adb7e3c..0000000000 --- a/hosting/Windows/Garnet.worker/Worker.cs +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -using System; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.Hosting; - -namespace Garnet -{ - public class Worker : BackgroundService - { - private bool _isDisposed = false; - private readonly string[] args; - - private GarnetServer server; - - public Worker(string[] args) - { - this.args = args; - } - - protected override async Task ExecuteAsync(CancellationToken stoppingToken) - { - try - { - server = new GarnetServer(args); - - // Start the server - server.Start(); - - await Task.Delay(Timeout.Infinite, stoppingToken).ConfigureAwait(false); - } - catch (Exception ex) - { - Console.WriteLine($"Unable to initialize server due to exception: {ex.Message}"); - } - } - - /// - /// Triggered when the application host is performing a graceful shutdown. - /// - /// Indicates that the shutdown process should no longer be graceful. - public override async Task StopAsync(CancellationToken cancellationToken) - { - Dispose(); - await base.StopAsync(cancellationToken).ConfigureAwait(false); - } - - public override void Dispose() - { - if (_isDisposed) - { - return; - } - server?.Dispose(); - _isDisposed = true; - } - } -} \ No newline at end of file diff --git a/libs/host/Factories/GarnetProviderFactory.cs b/libs/host/Factories/GarnetProviderFactory.cs new file mode 100644 index 0000000000..e1b9162fef --- /dev/null +++ b/libs/host/Factories/GarnetProviderFactory.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using Garnet.common; +using Garnet.server; +using Microsoft.Extensions.Options; +using Tsavorite.core; + +namespace Garnet; + +internal class GarnetProviderFactory +{ + readonly GarnetServerOptions options; + readonly SubscribeBroker> subscribeBroker; + readonly StoreWrapper storeWrapper; + + public GarnetProviderFactory( + IOptions options, + SubscribeBroker> subscribeBroker, + StoreWrapper storeWrapper) + { + this.options = options.Value; + this.subscribeBroker = subscribeBroker; + this.storeWrapper = storeWrapper; + } + + public GarnetProvider Create() + { + if (options.DisablePubSub) + { + return new GarnetProvider(storeWrapper, null); + } + + return new GarnetProvider(storeWrapper, subscribeBroker); + } +} \ No newline at end of file diff --git a/libs/host/Factories/StoreFactory.cs b/libs/host/Factories/StoreFactory.cs new file mode 100644 index 0000000000..9802c886ba --- /dev/null +++ b/libs/host/Factories/StoreFactory.cs @@ -0,0 +1,105 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using Garnet.server; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Tsavorite.core; + +namespace Garnet; + +using ObjectStoreAllocator = + GenericAllocator>>; +using ObjectStoreFunctions = + StoreFunctions>; + +internal class StoreFactory +{ + private readonly IClusterFactory clusterFactory; + private readonly GarnetServerOptions opts; + private readonly ILoggerFactory loggerFactory; + private readonly CustomCommandManager customCommandManager; + + public StoreFactory( + IClusterFactory clusterFactory, + IOptions options, + ILoggerFactory loggerFactory, + CustomCommandManager customCommandManager) + { + this.clusterFactory = options.Value.EnableCluster ? clusterFactory : null; + this.opts = options.Value; + this.loggerFactory = loggerFactory; + this.customCommandManager = customCommandManager; + } + + public MainStoreWrapper CreateMainStore() + { + var kvSettings = opts.GetSettings(loggerFactory, out var logFactory); + + var checkpointDir = opts.CheckpointDir ?? opts.LogDir; + + // Run checkpoint on its own thread to control p99 + kvSettings.ThrottleCheckpointFlushDelayMs = opts.CheckpointThrottleFlushDelayMs; + kvSettings.CheckpointVersionSwitchBarrier = opts.EnableCluster; + + var checkpointFactory = opts.DeviceFactoryCreator(); + if (opts.EnableCluster) + { + kvSettings.CheckpointManager = clusterFactory.CreateCheckpointManager(checkpointFactory, + new DefaultCheckpointNamingScheme(checkpointDir + "/Store/checkpoints"), isMainStore: true); + } + else + { + kvSettings.CheckpointManager = new DeviceLogCommitCheckpointManager(checkpointFactory, + new DefaultCheckpointNamingScheme(checkpointDir + "/Store/checkpoints"), removeOutdated: true); + } + + return new(new(kvSettings + , StoreFunctions.Create() + , (allocatorSettings, storeFunctions) => new(allocatorSettings, storeFunctions)), kvSettings); + } + + public ObjectStoreWrapper CreateObjectStore() + { + TsavoriteKV objectStore = null; + KVSettings objKvSettings = null; + CacheSizeTracker objectStoreSizeTracker = null; + + if (!opts.DisableObjects) + { + var checkpointDir = opts.CheckpointDir ?? opts.LogDir; + + objKvSettings = opts.GetObjectStoreSettings(loggerFactory?.CreateLogger("TsavoriteKV [obj]"), + out var objHeapMemorySize, out var objReadCacheHeapMemorySize); + + // Run checkpoint on its own thread to control p99 + objKvSettings.ThrottleCheckpointFlushDelayMs = opts.CheckpointThrottleFlushDelayMs; + objKvSettings.CheckpointVersionSwitchBarrier = opts.EnableCluster; + + if (opts.EnableCluster) + objKvSettings.CheckpointManager = clusterFactory.CreateCheckpointManager( + opts.DeviceFactoryCreator(), + new DefaultCheckpointNamingScheme(checkpointDir + "/ObjectStore/checkpoints"), + isMainStore: false); + else + objKvSettings.CheckpointManager = new DeviceLogCommitCheckpointManager( + opts.DeviceFactoryCreator(), + new DefaultCheckpointNamingScheme(checkpointDir + "/ObjectStore/checkpoints"), + removeOutdated: true); + + objectStore = new(objKvSettings + , StoreFunctions.Create(new ByteArrayKeyComparer(), + () => new ByteArrayBinaryObjectSerializer(), + () => new GarnetObjectSerializer(customCommandManager)) + , (allocatorSettings, storeFunctions) => new(allocatorSettings, storeFunctions)); + + if (objHeapMemorySize > 0 || objReadCacheHeapMemorySize > 0) + objectStoreSizeTracker = new CacheSizeTracker(objectStore, objKvSettings, objHeapMemorySize, + objReadCacheHeapMemorySize, + loggerFactory); + } + + return new(objectStore, objKvSettings, objectStoreSizeTracker); + } +} \ No newline at end of file diff --git a/libs/host/Factories/StoreWrapperFactory.cs b/libs/host/Factories/StoreWrapperFactory.cs new file mode 100644 index 0000000000..1627618682 --- /dev/null +++ b/libs/host/Factories/StoreWrapperFactory.cs @@ -0,0 +1,114 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using System; +using System.Linq; +using System.Text; +using Garnet.server; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Garnet; + +internal class StoreWrapperFactory +{ + /// + /// Resp protocol version + /// + readonly string redisProtocolVersion = "7.2.5"; + + readonly ILoggerFactory loggerFactory; + readonly ILogger logger; + readonly IGarnetServer garnetServer; + readonly GarnetServerOptions options; + readonly CustomCommandManager customCommandManager; + readonly IClusterFactory clusterFactory; + readonly MainStoreWrapper mainStoreWrapper; + readonly ObjectStoreWrapper objectStoreWrapper; + readonly AppendOnlyFileWrapper appendOnlyFileWrapper; + + public StoreWrapperFactory( + ILoggerFactory loggerFactory, + ILogger logger, + IGarnetServer garnetServer, + IOptions options, + CustomCommandManager customCommandManager, + IClusterFactory clusterFactory, + MainStoreWrapper mainStoreWrapper, + ObjectStoreWrapper objectStoreWrapper, + AppendOnlyFileWrapper appendOnlyFileWrapper) + { + this.loggerFactory = loggerFactory; + this.logger = logger; + this.garnetServer = garnetServer; + this.options = options.Value; + this.customCommandManager = customCommandManager; + this.clusterFactory = this.options.EnableCluster ? clusterFactory : null; + this.mainStoreWrapper = mainStoreWrapper; + this.objectStoreWrapper = objectStoreWrapper; + this.appendOnlyFileWrapper = appendOnlyFileWrapper; + } + + public StoreWrapper Create(string version) + { + var store = mainStoreWrapper.store; + var objectStore = objectStoreWrapper.objectStore; + var appendOnlyFile = appendOnlyFileWrapper.appendOnlyFile; + + var objectStoreSizeTracker = objectStoreWrapper.objectStoreSizeTracker; + + var configMemoryLimit = (store.IndexSize * 64) + store.Log.MaxMemorySizeBytes + + (store.ReadCache?.MaxMemorySizeBytes ?? 0) + + (appendOnlyFile?.MaxMemorySizeBytes ?? 0); + if (objectStore != null) + { + configMemoryLimit += objectStore.IndexSize * 64 + objectStore.Log.MaxMemorySizeBytes + + (objectStore.ReadCache?.MaxMemorySizeBytes ?? 0) + + (objectStoreSizeTracker?.TargetSize ?? 0) + + (objectStoreSizeTracker?.ReadCacheTargetSize ?? 0); + } + + logger.LogInformation("Total configured memory limit: {configMemoryLimit}", configMemoryLimit); + + LoadModules(); + + return new StoreWrapper( + version, + redisProtocolVersion, + garnetServer, + store, + objectStore, + objectStoreSizeTracker, + customCommandManager, + appendOnlyFile, + options, + clusterFactory: clusterFactory, + loggerFactory: loggerFactory); + } + + private void LoadModules() + { + if (options.LoadModuleCS == null) + return; + + foreach (var moduleCS in options.LoadModuleCS) + { + var moduleCSData = moduleCS.Split(' ', StringSplitOptions.RemoveEmptyEntries); + if (moduleCSData.Length < 1) + continue; + + var modulePath = moduleCSData[0]; + var moduleArgs = moduleCSData.Length > 1 ? moduleCSData.Skip(1).ToArray() : []; + if (ModuleUtils.LoadAssemblies([modulePath], null, true, out var loadedAssemblies, out var errorMsg)) + { + ModuleRegistrar.Instance.LoadModule(customCommandManager, loadedAssemblies.ToList()[0], moduleArgs, + logger, out errorMsg); + } + else + { + logger?.LogError("Module {0} failed to load with error {1}", modulePath, + Encoding.UTF8.GetString(errorMsg)); + } + } + } +} \ No newline at end of file diff --git a/libs/host/Garnet.host.csproj b/libs/host/Garnet.host.csproj index 1c1259fec3..afeca6f519 100644 --- a/libs/host/Garnet.host.csproj +++ b/libs/host/Garnet.host.csproj @@ -20,6 +20,8 @@ + + diff --git a/libs/host/GarnetApplicationBuilder.cs b/libs/host/GarnetApplicationBuilder.cs new file mode 100644 index 0000000000..cf5a54ed83 --- /dev/null +++ b/libs/host/GarnetApplicationBuilder.cs @@ -0,0 +1,179 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Reflection; +using Garnet.cluster; +using Garnet.common; +using Garnet.server; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.Metrics; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Tsavorite.core; + +namespace Garnet; + +public class GarnetApplicationBuilder : IHostApplicationBuilder +{ + readonly HostApplicationBuilder hostApplicationBuilder; + + public GarnetApplicationBuilder(GarnetApplicationOptions options, GarnetServerOptions garnetServerOptions) + { + var configuration = new ConfigurationManager(); + + configuration.AddEnvironmentVariables(prefix: "GARNET_"); + + hostApplicationBuilder = new HostApplicationBuilder(new HostApplicationBuilderSettings + { + Args = options.Args, + ApplicationName = options.ApplicationName, + EnvironmentName = options.EnvironmentName, + Configuration = configuration + }); + + hostApplicationBuilder.Services.AddOptions(); + + var garnetServerOptionsWrapped = Microsoft.Extensions.Options.Options.Create(garnetServerOptions); + hostApplicationBuilder.Services.AddSingleton(garnetServerOptionsWrapped); + + hostApplicationBuilder.Logging.ClearProviders(); + hostApplicationBuilder.Logging.AddSimpleConsole(simpleConsoleFormatterOptions => + { + simpleConsoleFormatterOptions.SingleLine = true; + simpleConsoleFormatterOptions.TimestampFormat = "hh::mm::ss "; + }); + hostApplicationBuilder.Logging.SetMinimumLevel(garnetServerOptions.LogLevel); + + hostApplicationBuilder.Services.AddTransient(); + hostApplicationBuilder.Services.AddTransient(); + hostApplicationBuilder.Services.AddTransient(); + hostApplicationBuilder.Services.AddTransient(); + + hostApplicationBuilder.Services.AddSingleton(); + + hostApplicationBuilder.Services.AddSingleton(sp => + { + var loggerFactory = sp.GetService(); + + var options = sp.GetRequiredService>(); + var opts = options.Value; + + var appendOnlyFileWrapper = new AppendOnlyFileWrapper(null, null); + + if (opts.EnableAOF) + { + if (opts.MainMemoryReplication && opts.CommitFrequencyMs != -1) + throw new Exception( + "Need to set CommitFrequencyMs to -1 (manual commits) with MainMemoryReplication"); + + opts.GetAofSettings(out var aofSettings); + + var aofDevice = aofSettings.LogDevice; + var appendOnlyFile = new TsavoriteLog(aofSettings, + logger: loggerFactory?.CreateLogger("TsavoriteLog [aof]")); + + appendOnlyFileWrapper = new AppendOnlyFileWrapper(aofDevice, appendOnlyFile); + + if (opts.CommitFrequencyMs < 0 && opts.WaitForCommit) + throw new Exception("Cannot use CommitWait with manual commits"); + + return appendOnlyFileWrapper; + } + + if (opts.CommitFrequencyMs != 0 || opts.WaitForCommit) + throw new Exception("Cannot use CommitFrequencyMs or CommitWait without EnableAOF"); + + return appendOnlyFileWrapper; + }); + + hostApplicationBuilder.Services.AddSingleton(sp => + { + var storeFactory = sp.GetRequiredService(); + + return storeFactory.CreateMainStore(); + }); + + hostApplicationBuilder.Services.AddSingleton(sp => + { + var storeFactory = sp.GetRequiredService(); + + return storeFactory.CreateObjectStore(); + }); + + hostApplicationBuilder.Services.AddSingleton(); + + hostApplicationBuilder.Services.AddSingleton(sp => + { + var options = sp.GetRequiredService>(); + var opts = options.Value; + + return new SubscribeBroker>( + new SpanByteKeySerializer(), null, opts.PubSubPageSizeBytes(), opts.SubscriberRefreshFrequencyMs, true); + }); + + hostApplicationBuilder.Services.AddSingleton(sp => + { + var storeWrapperFactory = sp.GetRequiredService(); + + var version = GetVersion(); + + return storeWrapperFactory.Create(version); + }); + + hostApplicationBuilder.Services.AddSingleton(sp => + { + var garnetProviderFactory = sp.GetRequiredService(); + + return garnetProviderFactory.Create(); + }); + + hostApplicationBuilder.Services.AddSingleton(); + hostApplicationBuilder.Services.AddSingleton(); + hostApplicationBuilder.Services.AddSingleton(); + + hostApplicationBuilder.Services.AddSingleton(); + + hostApplicationBuilder.Services.AddHostedService(); + } + + public GarnetApplication Build() + { + var host = hostApplicationBuilder.Build(); + return new GarnetApplication(host); + } + + public void ConfigureContainer(IServiceProviderFactory factory, + Action configure = null) + where TContainerBuilder : notnull + { + hostApplicationBuilder.ConfigureContainer(factory, configure); + } + + public IDictionary Properties { get; } + + public IConfigurationManager Configuration + => hostApplicationBuilder.Configuration; + + public IHostEnvironment Environment + => hostApplicationBuilder.Environment; + + public ILoggingBuilder Logging + => hostApplicationBuilder.Logging; + + public IMetricsBuilder Metrics + => hostApplicationBuilder.Metrics; + + public IServiceCollection Services + => hostApplicationBuilder.Services; + + + static string GetVersion() + { + var Version = Assembly.GetExecutingAssembly().GetName().Version; + return $"{Version.Major}.{Version.Minor}.{Version.Build}"; + } +} \ No newline at end of file diff --git a/libs/host/GarnetApplicationOptions.cs b/libs/host/GarnetApplicationOptions.cs new file mode 100644 index 0000000000..a7a6edfea7 --- /dev/null +++ b/libs/host/GarnetApplicationOptions.cs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +namespace Garnet; + +public class GarnetApplicationOptions +{ + /// + /// The command line arguments. + /// + public string[] Args { get; init; } + + /// + /// The environment name. + /// + public string EnvironmentName { get; init; } + + /// + /// The application name. + /// + public string ApplicationName { get; init; } +} \ No newline at end of file diff --git a/libs/host/GarnetApplicatrion.cs b/libs/host/GarnetApplicatrion.cs new file mode 100644 index 0000000000..ca324d5840 --- /dev/null +++ b/libs/host/GarnetApplicatrion.cs @@ -0,0 +1,108 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using System; +using System.Threading; +using System.Threading.Tasks; +using Garnet.common; +using Garnet.server; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace Garnet; + +public class GarnetApplication : IHost +{ + public MetricsApi Metrics + { + get + { + return host.Services.GetRequiredService(); + } + } + + public RegisterApi Register + { + get + { + return host.Services.GetRequiredService(); + } + } + + public StoreApi Store + { + get + { + return host.Services.GetRequiredService(); + } + } + + internal GarnetProvider Provider => host.Services.GetRequiredService(); + + readonly IHost host; + + public GarnetApplication(IHost host) + { + this.host = host; + } + + public Task StartAsync(CancellationToken cancellationToken = default) + => host.StartAsync(cancellationToken); + + public Task StopAsync(CancellationToken cancellationToken = default) + => host.StopAsync(cancellationToken); + + public IServiceProvider Services { get => host.Services; } + + public void Dispose() + { + host.Dispose(); + } + + public void Run() + { + HostingAbstractionsHostExtensions.Run(this); + } + + public Task RunAsync(CancellationToken cancellationToken = default) + { + HostingAbstractionsHostExtensions.RunAsync(this, cancellationToken); + return Task.CompletedTask; + } + + public static GarnetApplicationBuilder CreateHostBuilder(string[] args) + { + MemoryLogger initLogger; + + // Set up an initial memory logger to log messages from configuration parser into memory. + using (var memLogProvider = new MemoryLoggerProvider()) + { + initLogger = (MemoryLogger)memLogProvider.CreateLogger("ArgParser"); + } + + if (!ServerSettingsManager.TryParseCommandLineArguments(args, out var serverSettings, out _, + out var exitGracefully, initLogger)) + { + if (exitGracefully) + System.Environment.Exit(0); + + // Flush logs from memory logger + //initLogger.FlushLogger(logger); + + throw new GarnetException( + "Encountered an error when initializing Garnet server. Please see log messages above for more details."); + } + + var garnetServerOptions = serverSettings.GetServerOptions(null); + + return new(new GarnetApplicationOptions { Args = args }, garnetServerOptions); + } + + public static GarnetApplicationBuilder CreateHostBuilder(string[] args, GarnetServerOptions options) + { + return new(new GarnetApplicationOptions + { + Args = args, + }, options); + } +} \ No newline at end of file diff --git a/libs/host/GarnetServer.cs b/libs/host/GarnetServer.cs index c4af9b8dfe..4fa56e86f7 100644 --- a/libs/host/GarnetServer.cs +++ b/libs/host/GarnetServer.cs @@ -1,489 +1,203 @@ -// Copyright (c) Microsoft Corporation. +// Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Diagnostics; -using System.IO; -using System.Linq; using System.Reflection; -using System.Text; using System.Threading; -using Garnet.cluster; -using Garnet.common; using Garnet.networking; using Garnet.server; -using Garnet.server.Auth.Settings; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Tsavorite.core; -namespace Garnet +namespace Garnet; + +/// +/// Implementation Garnet server +/// +internal class GarnetServer : IDisposable { - using MainStoreAllocator = SpanByteAllocator>; - using MainStoreFunctions = StoreFunctions; + static readonly string version = GetVersion(); + + static string GetVersion() + { + var Version = Assembly.GetExecutingAssembly().GetName().Version; + return $"{Version.Major}.{Version.Minor}.{Version.Build}"; + } - using ObjectStoreAllocator = GenericAllocator>>; - using ObjectStoreFunctions = StoreFunctions>; + private readonly GarnetProvider provider; + private readonly GarnetServerOptions opts; + private readonly IGarnetServer server; + private readonly ILogger logger; + private readonly ILoggerFactory loggerFactory; + private readonly bool cleanupDir; /// - /// Implementation Garnet server + /// Create Garnet Server instance using GarnetServerOptions instance; use Start to start the server. /// - public class GarnetServer : IDisposable + /// Server options + /// Logger + /// Logger factory + /// The IGarnetServer to use. If none is provided, will use a GarnetServerTcp. + /// + public GarnetServer( + IOptions options, + ILogger logger, + ILoggerFactory loggerFactory, + IGarnetServer server, + GarnetProvider garnetProvider) { - static readonly string version = GetVersion(); - static string GetVersion() - { - var Version = Assembly.GetExecutingAssembly().GetName().Version; - return $"{Version.Major}.{Version.Minor}.{Version.Build}"; - } - - internal GarnetProvider Provider; - - private readonly GarnetServerOptions opts; - private IGarnetServer server; - private TsavoriteKV store; - private TsavoriteKV objectStore; - private IDevice aofDevice; - private TsavoriteLog appendOnlyFile; - private SubscribeBroker> subscribeBroker; - private KVSettings kvSettings; - private KVSettings objKvSettings; - private INamedDeviceFactory logFactory; - private MemoryLogger initLogger; - private ILogger logger; - private readonly ILoggerFactory loggerFactory; - private readonly bool cleanupDir; - private bool disposeLoggerFactory; - - /// - /// Store and associated information used by this Garnet server - /// - protected StoreWrapper storeWrapper; - - /// - /// Resp protocol version - /// - readonly string redisProtocolVersion = "7.2.5"; - - /// - /// Metrics API - /// - public MetricsApi Metrics; - - /// - /// Command registration API - /// - public RegisterApi Register; + this.server = server; + this.opts = options.Value; + this.logger = logger; + this.loggerFactory = loggerFactory; + this.provider = garnetProvider; + + this.cleanupDir = false; + this.InitializeServerUpdated(); + } - /// - /// Store API - /// - public StoreApi Store; + private void InitializeServerUpdated() + { + Debug.Assert(opts != null); - /// - /// Create Garnet Server instance using specified command line arguments; use Start to start the server. - /// - /// Command line arguments - /// Logger factory - /// Clean up directory. - /// Override for custom authentication settings. - public GarnetServer(string[] commandLineArgs, ILoggerFactory loggerFactory = null, bool cleanupDir = false, IAuthenticationSettings authenticationSettingsOverride = null) + if (!opts.QuietMode) { - Trace.Listeners.Add(new ConsoleTraceListener()); - - // Set up an initial memory logger to log messages from configuration parser into memory. - using (var memLogProvider = new MemoryLoggerProvider()) - { - this.initLogger = (MemoryLogger)memLogProvider.CreateLogger("ArgParser"); - } - - if (!ServerSettingsManager.TryParseCommandLineArguments(commandLineArgs, out var serverSettings, out _, out var exitGracefully, this.initLogger)) - { - if (exitGracefully) - Environment.Exit(0); - - // Flush logs from memory logger - FlushMemoryLogger(this.initLogger, "ArgParser", loggerFactory); - - throw new GarnetException("Encountered an error when initializing Garnet server. Please see log messages above for more details."); - } - - if (loggerFactory == null) - { - // If the main logger factory is created by GarnetServer, it should be disposed when GarnetServer is disposed - disposeLoggerFactory = true; - } - else - { - this.initLogger.LogWarning( - $"Received an external ILoggerFactory object. The following configuration options are ignored: {nameof(serverSettings.FileLogger)}, {nameof(serverSettings.LogLevel)}, {nameof(serverSettings.DisableConsoleLogger)}."); - } + var red = "\u001b[31m"; + var magenta = "\u001b[35m"; + var normal = "\u001b[0m"; + + Console.WriteLine($@"{red} _________ + /_||___||_\ {normal}Garnet {version} {(IntPtr.Size == 8 ? "64" : "32")} bit; {(opts.EnableCluster ? "cluster" : "standalone")} mode{red} + '. \ / .' {normal}Port: {opts.Port}{red} + '.\ /.' {magenta}https://aka.ms/GetGarnet{red} + '.' + {normal}"); + } - // If no logger factory is given, set up main logger factory based on parsed configuration values, - // otherwise use given logger factory. - this.loggerFactory = loggerFactory ?? LoggerFactory.Create(builder => - { - if (!serverSettings.DisableConsoleLogger.GetValueOrDefault()) - { - builder.AddSimpleConsole(options => - { - options.SingleLine = true; - options.TimestampFormat = "hh::mm::ss "; - }); - } + logger?.LogInformation("Garnet {version} {bits} bit; {clusterMode} mode; Port: {port}", version, + IntPtr.Size == 8 ? "64" : "32", opts.EnableCluster ? "cluster" : "standalone", opts.Port); - // Optional: Flush log output to file. - if (serverSettings.FileLogger != null) - builder.AddFile(serverSettings.FileLogger); - builder.SetMinimumLevel(serverSettings.LogLevel); - }); + // Flush initialization logs from memory logger + FlushMemoryLogger(null, "ArgParser", this.loggerFactory); - // Assign values to GarnetServerOptions - this.opts = serverSettings.GetServerOptions(this.loggerFactory.CreateLogger("Options")); - this.opts.AuthSettings = authenticationSettingsOverride ?? this.opts.AuthSettings; - this.cleanupDir = cleanupDir; - this.InitializeServer(); - } + ThreadPool.GetMinThreads(out var minThreads, out var minCPThreads); + ThreadPool.GetMaxThreads(out var maxThreads, out var maxCPThreads); - /// - /// Create Garnet Server instance using GarnetServerOptions instance; use Start to start the server. - /// - /// Server options - /// Logger factory - /// The IGarnetServer to use. If none is provided, will use a GarnetServerTcp. - /// Whether to clean up data folders on dispose - public GarnetServer(GarnetServerOptions opts, ILoggerFactory loggerFactory = null, IGarnetServer server = null, bool cleanupDir = false) + bool minChanged = false, maxChanged = false; + if (opts.ThreadPoolMinThreads > 0) { - this.server = server; - this.opts = opts; - this.loggerFactory = loggerFactory; - this.cleanupDir = cleanupDir; - this.InitializeServer(); + minThreads = opts.ThreadPoolMinThreads; + minChanged = true; } - private void InitializeServer() + if (opts.ThreadPoolMinIOCompletionThreads > 0) { - Debug.Assert(opts != null); - - if (!opts.QuietMode) - { - var red = "\u001b[31m"; - var magenta = "\u001b[35m"; - var normal = "\u001b[0m"; - - Console.WriteLine($@"{red} _________ - /_||___||_\ {normal}Garnet {version} {(IntPtr.Size == 8 ? "64" : "32")} bit; {(opts.EnableCluster ? "cluster" : "standalone")} mode{red} - '. \ / .' {normal}Port: {opts.Port}{red} - '.\ /.' {magenta}https://aka.ms/GetGarnet{red} - '.' -{normal}"); - } - - var clusterFactory = opts.EnableCluster ? new ClusterFactory() : null; - - this.logger = this.loggerFactory?.CreateLogger("GarnetServer"); - logger?.LogInformation("Garnet {version} {bits} bit; {clusterMode} mode; Port: {port}", version, IntPtr.Size == 8 ? "64" : "32", opts.EnableCluster ? "cluster" : "standalone", opts.Port); - - // Flush initialization logs from memory logger - FlushMemoryLogger(this.initLogger, "ArgParser", this.loggerFactory); - - var customCommandManager = new CustomCommandManager(); - - ThreadPool.GetMinThreads(out var minThreads, out var minCPThreads); - ThreadPool.GetMaxThreads(out var maxThreads, out var maxCPThreads); - - bool minChanged = false, maxChanged = false; - if (opts.ThreadPoolMinThreads > 0) - { - minThreads = opts.ThreadPoolMinThreads; - minChanged = true; - } - if (opts.ThreadPoolMinIOCompletionThreads > 0) - { - minCPThreads = opts.ThreadPoolMinIOCompletionThreads; - minChanged = true; - } - if (opts.ThreadPoolMaxThreads > 0) - { - maxThreads = opts.ThreadPoolMaxThreads; - maxChanged = true; - } - if (opts.ThreadPoolMaxIOCompletionThreads > 0) - { - maxCPThreads = opts.ThreadPoolMaxIOCompletionThreads; - maxChanged = true; - } - - // First try to set the max threads - var setMax = !maxChanged || ThreadPool.SetMaxThreads(maxThreads, maxCPThreads); - - // Set the min threads - if (minChanged && !ThreadPool.SetMinThreads(minThreads, minCPThreads)) - throw new Exception($"Unable to call ThreadPool.SetMinThreads with {minThreads}, {minCPThreads}"); - - // Retry to set max threads if it wasn't set in the earlier step - if (!setMax && !ThreadPool.SetMaxThreads(maxThreads, maxCPThreads)) - throw new Exception($"Unable to call ThreadPool.SetMaxThreads with {maxThreads}, {maxCPThreads}"); - - CreateMainStore(clusterFactory, out var checkpointDir); - CreateObjectStore(clusterFactory, customCommandManager, checkpointDir, out var objectStoreSizeTracker); - - if (!opts.DisablePubSub) - subscribeBroker = new SubscribeBroker>(new SpanByteKeySerializer(), null, opts.PubSubPageSizeBytes(), opts.SubscriberRefreshFrequencyMs, true); - - CreateAOF(); - - logger?.LogTrace("TLS is {tlsEnabled}", opts.TlsOptions == null ? "disabled" : "enabled"); - - if (logger != null) - { - var configMemoryLimit = (store.IndexSize * 64) + store.Log.MaxMemorySizeBytes + (store.ReadCache?.MaxMemorySizeBytes ?? 0) + (appendOnlyFile?.MaxMemorySizeBytes ?? 0); - if (objectStore != null) - configMemoryLimit += objectStore.IndexSize * 64 + objectStore.Log.MaxMemorySizeBytes + (objectStore.ReadCache?.MaxMemorySizeBytes ?? 0) + (objectStoreSizeTracker?.TargetSize ?? 0) + (objectStoreSizeTracker?.ReadCacheTargetSize ?? 0); - logger.LogInformation("Total configured memory limit: {configMemoryLimit}", configMemoryLimit); - } - - // Create Garnet TCP server if none was provided. - this.server ??= new GarnetServerTcp(opts.Address, opts.Port, 0, opts.TlsOptions, opts.NetworkSendThrottleMax, opts.NetworkConnectionLimit, logger); - - storeWrapper = new StoreWrapper(version, redisProtocolVersion, server, store, objectStore, objectStoreSizeTracker, - customCommandManager, appendOnlyFile, opts, clusterFactory: clusterFactory, loggerFactory: loggerFactory); - - // Create session provider for Garnet - Provider = new GarnetProvider(storeWrapper, subscribeBroker); - - // Create user facing API endpoints - Metrics = new MetricsApi(Provider); - Register = new RegisterApi(Provider); - Store = new StoreApi(storeWrapper); - - server.Register(WireFormat.ASCII, Provider); - - LoadModules(customCommandManager); + minCPThreads = opts.ThreadPoolMinIOCompletionThreads; + minChanged = true; } - private void LoadModules(CustomCommandManager customCommandManager) + if (opts.ThreadPoolMaxThreads > 0) { - if (opts.LoadModuleCS == null) - return; - - foreach (var moduleCS in opts.LoadModuleCS) - { - var moduleCSData = moduleCS.Split(' ', StringSplitOptions.RemoveEmptyEntries); - if (moduleCSData.Length < 1) - continue; - - var modulePath = moduleCSData[0]; - var moduleArgs = moduleCSData.Length > 1 ? moduleCSData.Skip(1).ToArray() : []; - if (ModuleUtils.LoadAssemblies([modulePath], null, true, out var loadedAssemblies, out var errorMsg)) - { - ModuleRegistrar.Instance.LoadModule(customCommandManager, loadedAssemblies.ToList()[0], moduleArgs, logger, out errorMsg); - } - else - { - logger?.LogError("Module {0} failed to load with error {1}", modulePath, Encoding.UTF8.GetString(errorMsg)); - } - } + maxThreads = opts.ThreadPoolMaxThreads; + maxChanged = true; } - private void CreateMainStore(IClusterFactory clusterFactory, out string checkpointDir) + if (opts.ThreadPoolMaxIOCompletionThreads > 0) { - kvSettings = opts.GetSettings(loggerFactory, out logFactory); - - checkpointDir = opts.CheckpointDir ?? opts.LogDir; - - // Run checkpoint on its own thread to control p99 - kvSettings.ThrottleCheckpointFlushDelayMs = opts.CheckpointThrottleFlushDelayMs; - kvSettings.CheckpointVersionSwitchBarrier = opts.EnableCluster; - - var checkpointFactory = opts.DeviceFactoryCreator(); - if (opts.EnableCluster) - { - kvSettings.CheckpointManager = clusterFactory.CreateCheckpointManager(checkpointFactory, - new DefaultCheckpointNamingScheme(checkpointDir + "/Store/checkpoints"), isMainStore: true, logger); - } - else - { - kvSettings.CheckpointManager = new DeviceLogCommitCheckpointManager(checkpointFactory, - new DefaultCheckpointNamingScheme(checkpointDir + "/Store/checkpoints"), removeOutdated: true); - } - - store = new(kvSettings - , StoreFunctions.Create() - , (allocatorSettings, storeFunctions) => new(allocatorSettings, storeFunctions)); + maxCPThreads = opts.ThreadPoolMaxIOCompletionThreads; + maxChanged = true; } - private void CreateObjectStore(IClusterFactory clusterFactory, CustomCommandManager customCommandManager, string CheckpointDir, out CacheSizeTracker objectStoreSizeTracker) - { - objectStoreSizeTracker = null; - if (!opts.DisableObjects) - { - objKvSettings = opts.GetObjectStoreSettings(this.loggerFactory?.CreateLogger("TsavoriteKV [obj]"), - out var objHeapMemorySize, out var objReadCacheHeapMemorySize); + // First try to set the max threads + var setMax = !maxChanged || ThreadPool.SetMaxThreads(maxThreads, maxCPThreads); - // Run checkpoint on its own thread to control p99 - objKvSettings.ThrottleCheckpointFlushDelayMs = opts.CheckpointThrottleFlushDelayMs; - objKvSettings.CheckpointVersionSwitchBarrier = opts.EnableCluster; + // Set the min threads + if (minChanged && !ThreadPool.SetMinThreads(minThreads, minCPThreads)) + throw new Exception($"Unable to call ThreadPool.SetMinThreads with {minThreads}, {minCPThreads}"); - if (opts.EnableCluster) - objKvSettings.CheckpointManager = clusterFactory.CreateCheckpointManager( - opts.DeviceFactoryCreator(), - new DefaultCheckpointNamingScheme(CheckpointDir + "/ObjectStore/checkpoints"), - isMainStore: false, logger); - else - objKvSettings.CheckpointManager = new DeviceLogCommitCheckpointManager(opts.DeviceFactoryCreator(), - new DefaultCheckpointNamingScheme(CheckpointDir + "/ObjectStore/checkpoints"), - removeOutdated: true); + // Retry to set max threads if it wasn't set in the earlier step + if (!setMax && !ThreadPool.SetMaxThreads(maxThreads, maxCPThreads)) + throw new Exception($"Unable to call ThreadPool.SetMaxThreads with {maxThreads}, {maxCPThreads}"); - objectStore = new(objKvSettings - , StoreFunctions.Create(new ByteArrayKeyComparer(), - () => new ByteArrayBinaryObjectSerializer(), - () => new GarnetObjectSerializer(customCommandManager)) - , (allocatorSettings, storeFunctions) => new(allocatorSettings, storeFunctions)); + logger?.LogTrace("TLS is {tlsEnabled}", opts.TlsOptions == null ? "disabled" : "enabled"); - if (objHeapMemorySize > 0 || objReadCacheHeapMemorySize > 0) - objectStoreSizeTracker = new CacheSizeTracker(objectStore, objKvSettings, objHeapMemorySize, objReadCacheHeapMemorySize, - this.loggerFactory); - } - } - - private void CreateAOF() - { - if (opts.EnableAOF) - { - if (opts.MainMemoryReplication && opts.CommitFrequencyMs != -1) - throw new Exception("Need to set CommitFrequencyMs to -1 (manual commits) with MainMemoryReplication"); - - opts.GetAofSettings(out var aofSettings); - aofDevice = aofSettings.LogDevice; - appendOnlyFile = new TsavoriteLog(aofSettings, logger: this.loggerFactory?.CreateLogger("TsavoriteLog [aof]")); - - if (opts.CommitFrequencyMs < 0 && opts.WaitForCommit) - throw new Exception("Cannot use CommitWait with manual commits"); - return; - } - - if (opts.CommitFrequencyMs != 0 || opts.WaitForCommit) - throw new Exception("Cannot use CommitFrequencyMs or CommitWait without EnableAOF"); - } + server.Register(WireFormat.ASCII, provider); + } - /// - /// Start server instance - /// - public void Start() - { - Provider.Recover(); - server.Start(); - Provider.Start(); - if (!opts.QuietMode) - Console.WriteLine("* Ready to accept connections"); - } + /// + /// Start server instance + /// + public void Start() + { + provider.Recover(); + server.Start(); + provider.Start(); + if (!opts.QuietMode) + Console.WriteLine("* Ready to accept connections"); + } - /// - /// Dispose store (including log and checkpoint directory) - /// - public void Dispose() - { - Dispose(cleanupDir); - } + /// + /// Dispose store (including log and checkpoint directory) + /// + public void Dispose() + { + server?.Dispose(); + Dispose(cleanupDir); + } - /// - /// Dispose, optionally deleting logs and checkpoints - /// - /// Whether to delete logs and checkpoints - public void Dispose(bool deleteDir = true) + /// + /// Dispose, optionally deleting logs and checkpoints + /// + /// Whether to delete logs and checkpoints + public void Dispose(bool deleteDir = true) + { + if (deleteDir) { - InternalDispose(); - if (deleteDir) + if (opts.CheckpointDir != opts.LogDir && !string.IsNullOrEmpty(opts.CheckpointDir)) { - logFactory?.Delete(new FileDescriptor { directoryName = "" }); - if (opts.CheckpointDir != opts.LogDir && !string.IsNullOrEmpty(opts.CheckpointDir)) - { - var ckptdir = opts.DeviceFactoryCreator(); - ckptdir.Initialize(opts.CheckpointDir); - ckptdir.Delete(new FileDescriptor { directoryName = "" }); - } + var ckptdir = opts.DeviceFactoryCreator(); + ckptdir.Initialize(opts.CheckpointDir); + ckptdir.Delete(new FileDescriptor { directoryName = "" }); } } + } - private void InternalDispose() - { - Provider?.Dispose(); - server.Dispose(); - subscribeBroker?.Dispose(); - store.Dispose(); - appendOnlyFile?.Dispose(); - aofDevice?.Dispose(); - kvSettings.LogDevice?.Dispose(); - if (!opts.DisableObjects) - { - objectStore.Dispose(); - objKvSettings.LogDevice?.Dispose(); - objKvSettings.ObjectLogDevice?.Dispose(); - } - opts.AuthSettings?.Dispose(); - if (disposeLoggerFactory) - loggerFactory?.Dispose(); - } + /// + /// Flushes MemoryLogger entries into a destination logger. + /// Destination logger is either created from ILoggerFactory parameter or from a default console logger. + /// + /// The memory logger + /// The category name of the destination logger + /// Optional logger factory for creating the destination logger + private static void FlushMemoryLogger(MemoryLogger memoryLogger, string categoryName, + ILoggerFactory dstLoggerFactory = null) + { + if (memoryLogger == null) return; - private static void DeleteDirectory(string path) + // If no logger factory supplied, create a default console logger + var disposeDstLoggerFactory = false; + if (dstLoggerFactory == null) { - if (path == null) return; - - // Exceptions may happen due to a handle briefly remaining held after Dispose(). - try - { - foreach (string directory in Directory.GetDirectories(path)) - { - DeleteDirectory(directory); - } - - Directory.Delete(path, true); - } - catch (Exception ex) when (ex is IOException || - ex is UnauthorizedAccessException) + dstLoggerFactory = LoggerFactory.Create(builder => builder.AddSimpleConsole(options => { - try - { - Directory.Delete(path, true); - } - catch { } - } + options.SingleLine = true; + options.TimestampFormat = "hh::mm::ss "; + }).SetMinimumLevel(LogLevel.Information)); + disposeDstLoggerFactory = true; } - /// - /// Flushes MemoryLogger entries into a destination logger. - /// Destination logger is either created from ILoggerFactory parameter or from a default console logger. - /// - /// The memory logger - /// The category name of the destination logger - /// Optional logger factory for creating the destination logger - private static void FlushMemoryLogger(MemoryLogger memoryLogger, string categoryName, ILoggerFactory dstLoggerFactory = null) - { - if (memoryLogger == null) return; + // Create the destination logger + var dstLogger = dstLoggerFactory.CreateLogger(categoryName); - // If no logger factory supplied, create a default console logger - var disposeDstLoggerFactory = false; - if (dstLoggerFactory == null) - { - dstLoggerFactory = LoggerFactory.Create(builder => builder.AddSimpleConsole(options => - { - options.SingleLine = true; - options.TimestampFormat = "hh::mm::ss "; - }).SetMinimumLevel(LogLevel.Information)); - disposeDstLoggerFactory = true; - } - - // Create the destination logger - var dstLogger = dstLoggerFactory.CreateLogger(categoryName); - - // Flush all entries from the memory logger into the destination logger - memoryLogger.FlushLogger(dstLogger); + // Flush all entries from the memory logger into the destination logger + memoryLogger.FlushLogger(dstLogger); - // If a default console logger factory was created, it is no longer needed - if (disposeDstLoggerFactory) - { - dstLoggerFactory.Dispose(); - } + // If a default console logger factory was created, it is no longer needed + if (disposeDstLoggerFactory) + { + dstLoggerFactory.Dispose(); } } } \ No newline at end of file diff --git a/libs/host/GarnetServerHostedService.cs b/libs/host/GarnetServerHostedService.cs new file mode 100644 index 0000000000..e068b071fd --- /dev/null +++ b/libs/host/GarnetServerHostedService.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using System; +using System.Diagnostics; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using Garnet.networking; +using Garnet.server; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Tsavorite.core; + +namespace Garnet; + +internal class GarnetServerHostedService : BackgroundService +{ + private readonly ILogger logger; + private readonly GarnetServer server; + + public GarnetServerHostedService( + ILogger logger, + GarnetServer server) + { + this.logger = logger; + this.server = server; + } + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + server.Start(); + + logger.LogInformation("Garnet server running at: {time}", DateTimeOffset.Now); + + await Task.CompletedTask; + } +} \ No newline at end of file diff --git a/libs/host/Wrappers/AppendOnlyFileWrapper.cs b/libs/host/Wrappers/AppendOnlyFileWrapper.cs new file mode 100644 index 0000000000..9886e7b5c6 --- /dev/null +++ b/libs/host/Wrappers/AppendOnlyFileWrapper.cs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using System; +using Tsavorite.core; + +namespace Garnet; + +internal class AppendOnlyFileWrapper : IDisposable +{ + readonly IDevice device; + public readonly TsavoriteLog appendOnlyFile; + + public AppendOnlyFileWrapper(IDevice device, TsavoriteLog appendOnlyFile) + { + this.device = device; + this.appendOnlyFile = appendOnlyFile; + } + + public void Dispose() + { + device?.Dispose(); + appendOnlyFile?.Dispose(); + } +} \ No newline at end of file diff --git a/libs/host/Wrappers/MainStoreWrapper.cs b/libs/host/Wrappers/MainStoreWrapper.cs new file mode 100644 index 0000000000..f6dc6c27ce --- /dev/null +++ b/libs/host/Wrappers/MainStoreWrapper.cs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using System; +using Tsavorite.core; + +namespace Garnet; + +using MainStoreAllocator = + SpanByteAllocator>; +using MainStoreFunctions = StoreFunctions; + +internal class MainStoreWrapper : IDisposable +{ + public readonly TsavoriteKV store; + + readonly KVSettings kvSettings; + + public MainStoreWrapper(TsavoriteKV store, + KVSettings kvSettings) + { + this.store = store; + this.kvSettings = kvSettings; + } + + public void Dispose() + { + store?.Dispose(); + kvSettings?.LogDevice?.Dispose(); + kvSettings?.Dispose(); + } +} \ No newline at end of file diff --git a/libs/host/Wrappers/ObjectStoreWrapper.cs b/libs/host/Wrappers/ObjectStoreWrapper.cs new file mode 100644 index 0000000000..3bb8301def --- /dev/null +++ b/libs/host/Wrappers/ObjectStoreWrapper.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using System; +using Garnet.server; +using Tsavorite.core; + +namespace Garnet; + +using ObjectStoreAllocator = + GenericAllocator>>; +using ObjectStoreFunctions = + StoreFunctions>; + +internal class ObjectStoreWrapper : IDisposable +{ + public readonly TsavoriteKV objectStore; + readonly KVSettings objKvSettings; + public readonly CacheSizeTracker objectStoreSizeTracker; + + public ObjectStoreWrapper( + TsavoriteKV objectStore, + KVSettings objKvSettings, + CacheSizeTracker objectStoreSizeTracker) + { + this.objectStore = objectStore; + this.objKvSettings = objKvSettings; + this.objectStoreSizeTracker = objectStoreSizeTracker; + } + + public void Dispose() + { + objectStore?.Dispose(); + objKvSettings?.LogDevice?.Dispose(); + objKvSettings?.ObjectLogDevice?.Dispose(); + objKvSettings?.Dispose(); + } +} \ No newline at end of file diff --git a/libs/server/Providers/GarnetProvider.cs b/libs/server/Providers/GarnetProvider.cs index 10665c94c1..afc6d2ff32 100644 --- a/libs/server/Providers/GarnetProvider.cs +++ b/libs/server/Providers/GarnetProvider.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +using System; using System.Threading; using Garnet.common; using Garnet.networking; @@ -52,14 +53,6 @@ public void Start() public void Recover() => storeWrapper.Recover(); - /// - /// Dispose - /// - public void Dispose() - { - storeWrapper.Dispose(); - } - /// public override SpanByteFunctionsForServer GetFunctions() => new(); diff --git a/libs/server/Servers/GarnetServerTcp.cs b/libs/server/Servers/GarnetServerTcp.cs index 09a1c4fd71..a23461f44d 100644 --- a/libs/server/Servers/GarnetServerTcp.cs +++ b/libs/server/Servers/GarnetServerTcp.cs @@ -10,214 +10,233 @@ using Garnet.networking; using Garnet.server.TLS; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; -namespace Garnet.server +namespace Garnet.server; + +/// +/// Garnet server for TCP +/// +public class GarnetServerTcp : GarnetServerBase, IServerHook, IDisposable { - /// - /// Garnet server for TCP - /// - public class GarnetServerTcp : GarnetServerBase, IServerHook + readonly SocketAsyncEventArgs acceptEventArg; + readonly Socket servSocket; + readonly IGarnetTlsOptions tlsOptions; + readonly int networkSendThrottleMax; + readonly NetworkBufferSettings networkBufferSettings; + readonly LimitedFixedBufferPool networkPool; + readonly int networkConnectionLimit; + + public IPEndPoint GetEndPoint { - readonly SocketAsyncEventArgs acceptEventArg; - readonly Socket servSocket; - readonly IGarnetTlsOptions tlsOptions; - readonly int networkSendThrottleMax; - readonly NetworkBufferSettings networkBufferSettings; - readonly LimitedFixedBufferPool networkPool; - readonly int networkConnectionLimit; - - public IPEndPoint GetEndPoint + get { - get - { - var ip = string.IsNullOrEmpty(Address) ? IPAddress.Any : IPAddress.Parse(Address); - return new IPEndPoint(ip, Port); - } + var ip = string.IsNullOrEmpty(Address) ? IPAddress.Any : IPAddress.Parse(Address); + return new IPEndPoint(ip, Port); } + } - /// - /// Get active consumers - /// - public override IEnumerable ActiveConsumers() + /// + /// Get active consumers + /// + public override IEnumerable ActiveConsumers() + { + foreach (var kvp in activeHandlers) { - foreach (var kvp in activeHandlers) - { - var consumer = kvp.Key.Session; - if (consumer != null) - yield return consumer; - } + var consumer = kvp.Key.Session; + if (consumer != null) + yield return consumer; } + } - /// - /// Get active consumers - /// - public IEnumerable ActiveClusterSessions() + /// + /// Get active consumers + /// + public IEnumerable ActiveClusterSessions() + { + foreach (var kvp in activeHandlers) { - foreach (var kvp in activeHandlers) - { - var consumer = kvp.Key.Session; - if (consumer != null) - yield return ((RespServerSession)consumer).clusterSession; - } + var consumer = kvp.Key.Session; + if (consumer != null) + yield return ((RespServerSession)consumer).clusterSession; } + } - /// - /// Constructor for server - /// - /// - /// - /// - /// - /// - /// - public GarnetServerTcp(string address, int port, int networkBufferSize = default, IGarnetTlsOptions tlsOptions = null, int networkSendThrottleMax = 8, int networkConnectionLimit = -1, ILogger logger = null) - : base(address, port, networkBufferSize, logger) - { - this.networkConnectionLimit = networkConnectionLimit; - this.tlsOptions = tlsOptions; - this.networkSendThrottleMax = networkSendThrottleMax; - var serverBufferSize = BufferSizeUtils.ServerBufferSize(new MaxSizeSettings()); - this.networkBufferSettings = new NetworkBufferSettings(serverBufferSize, serverBufferSize); - this.networkPool = networkBufferSettings.CreateBufferPool(logger: logger); - servSocket = new Socket(GetEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); - acceptEventArg = new SocketAsyncEventArgs(); - acceptEventArg.Completed += AcceptEventArg_Completed; - } + /// + /// Constructor for server + /// + /// + /// + public GarnetServerTcp(IOptions options, ILogger logger) + : base(options.Value.Address, options.Value.Port, 0, logger) + { + this.networkConnectionLimit = options.Value.NetworkConnectionLimit; + this.tlsOptions = options.Value.TlsOptions; + this.networkSendThrottleMax = options.Value.NetworkSendThrottleMax; + var serverBufferSize = BufferSizeUtils.ServerBufferSize(new MaxSizeSettings()); + this.networkBufferSettings = new NetworkBufferSettings(serverBufferSize, serverBufferSize); + this.networkPool = networkBufferSettings.CreateBufferPool(logger: logger); + servSocket = new Socket(GetEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + acceptEventArg = new SocketAsyncEventArgs(); + acceptEventArg.Completed += AcceptEventArg_Completed; + } - /// - /// Dispose - /// - public override void Dispose() - { - base.Dispose(); - servSocket.Dispose(); - acceptEventArg.UserToken = null; - acceptEventArg.Dispose(); - networkPool?.Dispose(); - } + /// + /// Constructor for server + /// + /// + /// + /// + /// + /// + /// + public GarnetServerTcp(string address, int port, int networkBufferSize = default, IGarnetTlsOptions tlsOptions = null, int networkSendThrottleMax = 8, int networkConnectionLimit = -1, ILogger logger = null) + : base(address, port, networkBufferSize, logger) + { + this.networkConnectionLimit = networkConnectionLimit; + this.tlsOptions = tlsOptions; + this.networkSendThrottleMax = networkSendThrottleMax; + var serverBufferSize = BufferSizeUtils.ServerBufferSize(new MaxSizeSettings()); + this.networkBufferSettings = new NetworkBufferSettings(serverBufferSize, serverBufferSize); + this.networkPool = networkBufferSettings.CreateBufferPool(logger: logger); + servSocket = new Socket(GetEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + acceptEventArg = new SocketAsyncEventArgs(); + acceptEventArg.Completed += AcceptEventArg_Completed; + } - /// - /// Start listening to incoming requests - /// - public override void Start() - { - var endPoint = GetEndPoint; - servSocket.Bind(endPoint); - servSocket.Listen(512); - if (!servSocket.AcceptAsync(acceptEventArg)) - AcceptEventArg_Completed(null, acceptEventArg); - } + /// + /// Dispose + /// + public override void Dispose() + { + base.Dispose(); + servSocket.Dispose(); + acceptEventArg.UserToken = null; + acceptEventArg.Dispose(); + networkPool?.Dispose(); + } + + /// + /// Start listening to incoming requests + /// + public override void Start() + { + var endPoint = GetEndPoint; + servSocket.Bind(endPoint); + servSocket.Listen(512); + if (!servSocket.AcceptAsync(acceptEventArg)) + AcceptEventArg_Completed(null, acceptEventArg); + } - private void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e) + private void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e) + { + try { - try + do { - do - { - if (!HandleNewConnection(e)) break; - e.AcceptSocket = null; - } while (!servSocket.AcceptAsync(e)); - } - // socket disposed - catch (ObjectDisposedException) { } + if (!HandleNewConnection(e)) break; + e.AcceptSocket = null; + } while (!servSocket.AcceptAsync(e)); } + // socket disposed + catch (ObjectDisposedException) { } + } - private unsafe bool HandleNewConnection(SocketAsyncEventArgs e) + private unsafe bool HandleNewConnection(SocketAsyncEventArgs e) + { + if (e.SocketError != SocketError.Success) { - if (e.SocketError != SocketError.Success) - { - e.Dispose(); - return false; - } + e.Dispose(); + return false; + } - e.AcceptSocket.NoDelay = true; + e.AcceptSocket.NoDelay = true; - // Ok to create new event args on accept because we assume a connection to be long-running - string remoteEndpointName = e.AcceptSocket.RemoteEndPoint?.ToString(); - logger?.LogDebug("Accepted TCP connection from {remoteEndpoint}", remoteEndpointName); + // Ok to create new event args on accept because we assume a connection to be long-running + string remoteEndpointName = e.AcceptSocket.RemoteEndPoint?.ToString(); + logger?.LogDebug("Accepted TCP connection from {remoteEndpoint}", remoteEndpointName); - ServerTcpNetworkHandler handler = null; - if (activeHandlerCount >= 0) + ServerTcpNetworkHandler handler = null; + if (activeHandlerCount >= 0) + { + var currentActiveHandlerCount = Interlocked.Increment(ref activeHandlerCount); + if (currentActiveHandlerCount > 0 && (networkConnectionLimit == -1 || currentActiveHandlerCount <= networkConnectionLimit)) { - var currentActiveHandlerCount = Interlocked.Increment(ref activeHandlerCount); - if (currentActiveHandlerCount > 0 && (networkConnectionLimit == -1 || currentActiveHandlerCount <= networkConnectionLimit)) + try { - try - { - handler = new ServerTcpNetworkHandler(this, e.AcceptSocket, networkBufferSettings, networkPool, tlsOptions != null, networkSendThrottleMax: networkSendThrottleMax, logger: logger); - if (!activeHandlers.TryAdd(handler, default)) - throw new Exception("Unable to add handler to dictionary"); - - handler.Start(tlsOptions?.TlsServerOptions, remoteEndpointName); - incr_conn_recv(); - return true; - } - catch (Exception ex) - { - logger?.LogError(ex, "Error starting network handler"); - Interlocked.Decrement(ref activeHandlerCount); - handler?.Dispose(); - } + handler = new ServerTcpNetworkHandler(this, e.AcceptSocket, networkBufferSettings, networkPool, tlsOptions != null, networkSendThrottleMax: networkSendThrottleMax, logger: logger); + if (!activeHandlers.TryAdd(handler, default)) + throw new Exception("Unable to add handler to dictionary"); + + handler.Start(tlsOptions?.TlsServerOptions, remoteEndpointName); + incr_conn_recv(); + return true; } - else + catch (Exception ex) { + logger?.LogError(ex, "Error starting network handler"); Interlocked.Decrement(ref activeHandlerCount); - e.AcceptSocket.Dispose(); + handler?.Dispose(); } } - return true; + else + { + Interlocked.Decrement(ref activeHandlerCount); + e.AcceptSocket.Dispose(); + } } + return true; + } - /// - /// Create session (message consumer) given incoming bytes - /// - /// - /// - /// - /// - public bool TryCreateMessageConsumer(Span bytes, INetworkSender networkSender, out IMessageConsumer session) - { - session = null; + /// + /// Create session (message consumer) given incoming bytes + /// + /// + /// + /// + /// + public bool TryCreateMessageConsumer(Span bytes, INetworkSender networkSender, out IMessageConsumer session) + { + session = null; - // We need at least 4 bytes to determine session - if (bytes.Length < 4) - return false; + // We need at least 4 bytes to determine session + if (bytes.Length < 4) + return false; - WireFormat protocol = WireFormat.ASCII; + WireFormat protocol = WireFormat.ASCII; - if (!GetSessionProviders().TryGetValue(protocol, out var provider)) - { - var input = System.Text.Encoding.ASCII.GetString(bytes); - logger?.LogError("Cannot identify wire protocol {bytes}", input); - throw new Exception($"Unsupported incoming wire format {protocol} {input}"); - } + if (!GetSessionProviders().TryGetValue(protocol, out var provider)) + { + var input = System.Text.Encoding.ASCII.GetString(bytes); + logger?.LogError("Cannot identify wire protocol {bytes}", input); + throw new Exception($"Unsupported incoming wire format {protocol} {input}"); + } - if (!AddSession(protocol, ref provider, networkSender, out session)) - throw new Exception($"Unable to add session"); + if (!AddSession(protocol, ref provider, networkSender, out session)) + throw new Exception($"Unable to add session"); - return true; - } + return true; + } - /// - public void DisposeMessageConsumer(INetworkHandler session) + /// + public void DisposeMessageConsumer(INetworkHandler session) + { + if (activeHandlers.TryRemove(session, out _)) { - if (activeHandlers.TryRemove(session, out _)) + Interlocked.Decrement(ref activeHandlerCount); + incr_conn_disp(); + try { - Interlocked.Decrement(ref activeHandlerCount); - incr_conn_disp(); - try - { - session.Session?.Dispose(); - } - catch (Exception ex) - { - logger?.LogError(ex, "Error disposing RespServerSession"); - } + session.Session?.Dispose(); + } + catch (Exception ex) + { + logger?.LogError(ex, "Error disposing RespServerSession"); } } + } - public void Purge() => networkPool.Purge(); + public void Purge() => networkPool.Purge(); - public string GetBufferPoolStats() => networkPool.GetStats(); - } + public string GetBufferPoolStats() => networkPool.GetStats(); } \ No newline at end of file diff --git a/libs/server/StoreWrapper.cs b/libs/server/StoreWrapper.cs index 6da4f7fca5..2af62e8f71 100644 --- a/libs/server/StoreWrapper.cs +++ b/libs/server/StoreWrapper.cs @@ -26,7 +26,7 @@ namespace Garnet.server /// /// Wrapper for store and store-specific information /// - public sealed class StoreWrapper + public sealed class StoreWrapper : IDisposable { internal readonly string version; internal readonly string redisProtocolVersion; diff --git a/main/GarnetServer/Program.cs b/main/GarnetServer/Program.cs index 314a6a39ba..12d0abe54b 100644 --- a/main/GarnetServer/Program.cs +++ b/main/GarnetServer/Program.cs @@ -1,99 +1,77 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -using System; -using System.Threading; +using Garnet; using Garnet.server; -namespace Garnet -{ - /// - /// Garnet server entry point - /// - class Program - { - static void Main(string[] args) - { - try - { - using var server = new GarnetServer(args); +var builder = GarnetApplication.CreateHostBuilder(args); - // Optional: register custom extensions - RegisterExtensions(server); +var app = builder.Build(); - // Start the server - server.Start(); +RegisterExtensions(app); - Thread.Sleep(Timeout.Infinite); - } - catch (Exception ex) - { - Console.WriteLine($"Unable to initialize server due to exception: {ex.Message}"); - } - } +app.Run(); - /// - /// Register new commands with the server. You can access these commands from clients using - /// commands such as db.Execute in StackExchange.Redis. Example: - /// db.Execute("SETIFPM", key, value, prefix); - /// - static void RegisterExtensions(GarnetServer server) - { - // Register custom command on raw strings (SETIFPM = "set if prefix match") - // Add RESP command info to registration for command to appear when client runs COMMAND / COMMAND INFO - var setIfPmCmdInfo = new RespCommandsInfo - { - Name = "SETIFPM", - Arity = 4, - FirstKey = 1, - LastKey = 1, - Step = 1, - Flags = RespCommandFlags.DenyOom | RespCommandFlags.Write, - AclCategories = RespAclCategories.String | RespAclCategories.Write, - }; - server.Register.NewCommand("SETIFPM", CommandType.ReadModifyWrite, new SetIfPMCustomCommand(), setIfPmCmdInfo); +/// +/// Register new commands with the server. You can access these commands from clients using +/// commands such as db.Execute in StackExchange.Redis. Example: +/// db.Execute("SETIFPM", key, value, prefix); +/// +static void RegisterExtensions(GarnetApplication server) +{ + // Register custom command on raw strings (SETIFPM = "set if prefix match") + // Add RESP command info to registration for command to appear when client runs COMMAND / COMMAND INFO + var setIfPmCmdInfo = new RespCommandsInfo + { + Name = "SETIFPM", + Arity = 4, + FirstKey = 1, + LastKey = 1, + Step = 1, + Flags = RespCommandFlags.DenyOom | RespCommandFlags.Write, + AclCategories = RespAclCategories.String | RespAclCategories.Write, + }; + server.Register.NewCommand("SETIFPM", CommandType.ReadModifyWrite, new SetIfPMCustomCommand(), setIfPmCmdInfo); - // Register custom command on raw strings (SETWPIFPGT = "set with prefix, if prefix greater than") - server.Register.NewCommand("SETWPIFPGT", CommandType.ReadModifyWrite, new SetWPIFPGTCustomCommand()); + // Register custom command on raw strings (SETWPIFPGT = "set with prefix, if prefix greater than") + server.Register.NewCommand("SETWPIFPGT", CommandType.ReadModifyWrite, new SetWPIFPGTCustomCommand()); - // Register custom command on raw strings (DELIFM = "delete if value matches") - server.Register.NewCommand("DELIFM", CommandType.ReadModifyWrite, new DeleteIfMatchCustomCommand()); + // Register custom command on raw strings (DELIFM = "delete if value matches") + server.Register.NewCommand("DELIFM", CommandType.ReadModifyWrite, new DeleteIfMatchCustomCommand()); - // Register custom commands on objects - var factory = new MyDictFactory(); - server.Register.NewType(factory); - server.Register.NewCommand("MYDICTSET", CommandType.ReadModifyWrite, factory, new MyDictSet(), new RespCommandsInfo { Arity = 4 }); - server.Register.NewCommand("MYDICTGET", CommandType.Read, factory, new MyDictGet(), new RespCommandsInfo { Arity = 3 }); + // Register custom commands on objects + var factory = new MyDictFactory(); + server.Register.NewType(factory); + server.Register.NewCommand("MYDICTSET", CommandType.ReadModifyWrite, factory, new MyDictSet(), new RespCommandsInfo { Arity = 4 }); + server.Register.NewCommand("MYDICTGET", CommandType.Read, factory, new MyDictGet(), new RespCommandsInfo { Arity = 3 }); - // Register stored procedure to run a transactional command - // Add RESP command info to registration for command to appear when client runs COMMAND / COMMAND INFO - var readWriteTxCmdInfo = new RespCommandsInfo - { - Name = "READWRITETX", - Arity = 4, - FirstKey = 1, - LastKey = 3, - Step = 1, - Flags = RespCommandFlags.DenyOom | RespCommandFlags.Write, - AclCategories = RespAclCategories.Write, - }; - server.Register.NewTransactionProc("READWRITETX", () => new ReadWriteTxn(), readWriteTxCmdInfo); + // Register stored procedure to run a transactional command + // Add RESP command info to registration for command to appear when client runs COMMAND / COMMAND INFO + var readWriteTxCmdInfo = new RespCommandsInfo + { + Name = "READWRITETX", + Arity = 4, + FirstKey = 1, + LastKey = 3, + Step = 1, + Flags = RespCommandFlags.DenyOom | RespCommandFlags.Write, + AclCategories = RespAclCategories.Write, + }; + server.Register.NewTransactionProc("READWRITETX", () => new ReadWriteTxn(), readWriteTxCmdInfo); - // Register stored procedure to run a transactional command - server.Register.NewTransactionProc("MSETPX", () => new MSetPxTxn()); + // Register stored procedure to run a transactional command + server.Register.NewTransactionProc("MSETPX", () => new MSetPxTxn()); - // Register stored procedure to run a transactional command - server.Register.NewTransactionProc("MGETIFPM", () => new MGetIfPM()); + // Register stored procedure to run a transactional command + server.Register.NewTransactionProc("MGETIFPM", () => new MGetIfPM()); - // Register stored procedure to run a non-transactional command - server.Register.NewTransactionProc("GETTWOKEYSNOTXN", () => new GetTwoKeysNoTxn(), new RespCommandsInfo { Arity = 3 }); + // Register stored procedure to run a non-transactional command + server.Register.NewTransactionProc("GETTWOKEYSNOTXN", () => new GetTwoKeysNoTxn(), new RespCommandsInfo { Arity = 3 }); - // Register sample transactional procedures - server.Register.NewTransactionProc("SAMPLEUPDATETX", () => new SampleUpdateTxn(), new RespCommandsInfo { Arity = 9 }); - server.Register.NewTransactionProc("SAMPLEDELETETX", () => new SampleDeleteTxn(), new RespCommandsInfo { Arity = 6 }); + // Register sample transactional procedures + server.Register.NewTransactionProc("SAMPLEUPDATETX", () => new SampleUpdateTxn(), new RespCommandsInfo { Arity = 9 }); + server.Register.NewTransactionProc("SAMPLEDELETETX", () => new SampleDeleteTxn(), new RespCommandsInfo { Arity = 6 }); - server.Register.NewProcedure("SUM", () => new Sum()); - server.Register.NewProcedure("SETMAINANDOBJECT", () => new SetStringAndList()); - } - } + server.Register.NewProcedure("SUM", () => new Sum()); + server.Register.NewProcedure("SETMAINANDOBJECT", () => new SetStringAndList()); } \ No newline at end of file diff --git a/playground/Embedded.perftest/Embedded.perftest.csproj b/playground/Embedded.perftest/Embedded.perftest.csproj index 9ac00ea182..9d2418946b 100644 --- a/playground/Embedded.perftest/Embedded.perftest.csproj +++ b/playground/Embedded.perftest/Embedded.perftest.csproj @@ -12,7 +12,8 @@ - + + diff --git a/playground/Embedded.perftest/EmbeddedPerformanceTest.cs b/playground/Embedded.perftest/EmbeddedPerformanceTest.cs index e7eaf898c8..277bee8d11 100644 --- a/playground/Embedded.perftest/EmbeddedPerformanceTest.cs +++ b/playground/Embedded.perftest/EmbeddedPerformanceTest.cs @@ -25,7 +25,7 @@ internal class EmbeddedPerformanceTest /// /// Embedded server instance to issue commands to /// - readonly EmbeddedRespServer server; + readonly GarnetEmbeddedApplication server; /// /// Logger used to log test progress @@ -48,7 +48,7 @@ internal class EmbeddedPerformanceTest /// Test options. /// Factory to create the status logger for the test /// Thrown if given configuration is invalid. - public EmbeddedPerformanceTest(EmbeddedRespServer server, Options opts, ILoggerFactory loggerFactory) + public EmbeddedPerformanceTest(GarnetEmbeddedApplication server, Options opts, ILoggerFactory loggerFactory) { this.server = server; this.opts = opts; diff --git a/playground/Embedded.perftest/GarnetEmbeddedApplicationBuilder.cs b/playground/Embedded.perftest/GarnetEmbeddedApplicationBuilder.cs new file mode 100644 index 0000000000..22eb894965 --- /dev/null +++ b/playground/Embedded.perftest/GarnetEmbeddedApplicationBuilder.cs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +using System; +using System.Linq; +using Embedded.server; +using Garnet; +using Garnet.server; +using Microsoft.Extensions.DependencyInjection; + +namespace Embedded.perftest; + +internal class GarnetEmbeddedApplicationBuilder : GarnetApplicationBuilder +{ + internal GarnetEmbeddedApplicationBuilder(GarnetApplicationOptions options, GarnetServerOptions garnetServerOptions) + : base(options, garnetServerOptions) + { + } + + public new GarnetEmbeddedApplication Build() + { + var serviceDescriptor = base.Services + .FirstOrDefault(descriptor => descriptor.ServiceType == typeof(IGarnetServer)); + + base.Services.Remove(serviceDescriptor); + + base.Services.AddSingleton(); + + var app = base.Build(); + + return new GarnetEmbeddedApplication(app); + } +} \ No newline at end of file diff --git a/playground/Embedded.perftest/Program.cs b/playground/Embedded.perftest/Program.cs index 914ab0b170..243c32c960 100644 --- a/playground/Embedded.perftest/Program.cs +++ b/playground/Embedded.perftest/Program.cs @@ -4,90 +4,95 @@ using System; using CommandLine; using Embedded.server; +using Garnet; using Garnet.common; using Garnet.server; using Microsoft.Extensions.Logging; -namespace Embedded.perftest +namespace Embedded.perftest; + +/// +/// Performance test for the core processing loop of embedded (in-process) Garnet instances. +/// +/// NOTE: This performance test is designed to specifically stress-test the core RESP processing loop +/// of Garnet and, as such, tries to keep actual data manipulation minimal. +/// In its current form this is not a replacement for a full benchmark that can execute +/// on a larger data set. +/// +internal class Program { - /// - /// Performance test for the core processing loop of embedded (in-process) Garnet instances. - /// - /// NOTE: This performance test is designed to specifically stress-test the core RESP processing loop - /// of Garnet and, as such, tries to keep actual data manipulation minimal. - /// In its current form this is not a replacement for a full benchmark that can execute - /// on a larger data set. - /// - internal class Program + static void Main(string[] args) { - static void Main(string[] args) + // Parse and initialize test parameters + ParserResult result = Parser.Default.ParseArguments(args); + + if (result.Tag == ParserResultType.NotParsed) { - // Parse and initialize test parameters - ParserResult result = Parser.Default.ParseArguments(args); + return; + } - if (result.Tag == ParserResultType.NotParsed) - { - return; - } + var opts = result.MapResult(o => o, xs => new Options()); - var opts = result.MapResult(o => o, xs => new Options()); + var loggerFactory = CreateLoggerFactory(opts); - var loggerFactory = CreateLoggerFactory(opts); + // Create embedded Garnet server in-process + GarnetServerOptions opt = new GarnetServerOptions + { + QuietMode = true + }; - // Create embedded Garnet server in-process - GarnetServerOptions opt = new GarnetServerOptions - { - QuietMode = true - }; - using var server = new EmbeddedRespServer(opt, loggerFactory); + //using var server = new EmbeddedRespServer(opt, loggerFactory); - PrintBenchmarkConfig(opts); + var builder = GarnetEmbeddedApplication.CreateHostBuilder([], opt); - // Run performance test - var perfTest = new EmbeddedPerformanceTest(server, opts, loggerFactory); - perfTest.Run(); + var app = builder.Build(); - return; - } + PrintBenchmarkConfig(opts); + + // Run performance test + var perfTest = new EmbeddedPerformanceTest(app, opts, loggerFactory); + perfTest.Run(); + + return; + } - /// - /// Create logger factory with the given test options - /// - static ILoggerFactory CreateLoggerFactory(Options opts) + /// + /// Create logger factory with the given test options + /// + static ILoggerFactory CreateLoggerFactory(Options opts) + { + return LoggerFactory.Create(builder => { - return LoggerFactory.Create(builder => + // Unless disabled, add console logger provider + if (!opts.DisableConsoleLogger) { - // Unless disabled, add console logger provider - if (!opts.DisableConsoleLogger) - { - builder.AddProvider(new PerformanceTestLoggerProvider(Console.Out)); - } - - // Optional: Flush log output to file. - if (opts.FileLogger != null) - { - builder.AddFile(opts.FileLogger); - } - - // Set logging level - builder.SetMinimumLevel(opts.LogLevel); - }); - } + builder.AddProvider(new PerformanceTestLoggerProvider(Console.Out)); + } - /// - /// Print a human-readable representation of the given test options - /// - /// Options to print - static void PrintBenchmarkConfig(Options opts) - { - Console.WriteLine("============== Configuration =============="); - Console.WriteLine($"Run time : {opts.RunTime} seconds"); - Console.WriteLine($"# Threads : {String.Join(", ", opts.NumThreads)}"); - Console.WriteLine($"Batch Size : {opts.BatchSize} operations"); - Console.WriteLine($"OpWorkload : {String.Join(", ", opts.OpWorkload)}"); - Console.WriteLine($"OpPercent : {String.Join(", ", opts.OpPercent)}"); - Console.WriteLine($"RNG Seed : {opts.Seed}"); - Console.WriteLine("==========================================="); - } + // Optional: Flush log output to file. + if (opts.FileLogger != null) + { + builder.AddFile(opts.FileLogger); + } + + // Set logging level + builder.SetMinimumLevel(opts.LogLevel); + }); + } + + /// + /// Print a human-readable representation of the given test options + /// + /// Options to print + static void PrintBenchmarkConfig(Options opts) + { + Console.WriteLine("============== Configuration =============="); + Console.WriteLine($"Run time : {opts.RunTime} seconds"); + Console.WriteLine($"# Threads : {String.Join(", ", opts.NumThreads)}"); + Console.WriteLine($"Batch Size : {opts.BatchSize} operations"); + Console.WriteLine($"OpWorkload : {String.Join(", ", opts.OpWorkload)}"); + Console.WriteLine($"OpPercent : {String.Join(", ", opts.OpPercent)}"); + Console.WriteLine($"RNG Seed : {opts.Seed}"); + Console.WriteLine("==========================================="); } } \ No newline at end of file diff --git a/playground/TstRunner/Program.cs b/playground/TstRunner/Program.cs index ad8d1b36a2..8f54557eed 100644 --- a/playground/TstRunner/Program.cs +++ b/playground/TstRunner/Program.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics; +using System.Threading.Tasks; using Garnet.test; using Garnet.test.cluster; @@ -10,7 +11,7 @@ namespace TstRunner { public class Program { - static void Main() + static async Task Main() { //Trace.Listeners.Add(new ConsoleTraceListener()); @@ -42,7 +43,7 @@ static void Main() clusterReplicationTests.SetLogTextWriter(Console.Out); var clusterReplicationTestItems = clusterReplicationTests.GetUnitTests(); foreach (var item in clusterReplicationTestItems) - RunTest(clusterReplicationTests, item.Item1, item.Item2); + await RunTest(clusterReplicationTests, item.Item1, item.Item2); swatch.Stop(); Console.WriteLine($">>>>>>>>>> run: {i++} duration (sec):{swatch.ElapsedMilliseconds / 1000}"); @@ -50,14 +51,14 @@ static void Main() } } - private static void RunTest(T test, Action testCase, string name = "") + private static async Task RunTest(T test, Task testCase, string name = "") { dynamic ctest = test; try { Console.WriteLine($"\tStarted {name} on {DateTime.Now}"); ctest.Setup(); - testCase(); + await testCase; } finally { diff --git a/test/Garnet.test.cluster/ClusterAadAuthTests.cs b/test/Garnet.test.cluster/ClusterAadAuthTests.cs index 86d6bce69d..47f981ca85 100644 --- a/test/Garnet.test.cluster/ClusterAadAuthTests.cs +++ b/test/Garnet.test.cluster/ClusterAadAuthTests.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Security.Claims; +using System.Threading.Tasks; using Garnet.server.Auth.Settings; using Microsoft.Extensions.Logging; using Microsoft.IdentityModel.Tokens; @@ -39,7 +40,7 @@ public void TearDown() [Test, Order(1)] [Category("CLUSTER-AUTH"), CancelAfter(60000)] - public void ValidateClusterAuthWithObjectId() + public async Task ValidateClusterAuthWithObjectId() { var nodes = 2; var audience = Guid.NewGuid().ToString(); @@ -56,12 +57,12 @@ public void ValidateClusterAuthWithObjectId() var authSettings = new AadAuthenticationSettings([appId], [audience], [issuer], new MockIssuerSigningTokenProvider(new List { tokenGenerator.SecurityKey }, context.logger), true); var token = tokenGenerator.CreateToken(tokenClaims, DateTime.Now.AddMinutes(10)); - ValidateConnectionsWithToken(objId, token, nodes, authSettings); + await ValidateConnectionsWithToken(objId, token, nodes, authSettings); } [Test, Order(2)] [Category("CLUSTER-AUTH"), CancelAfter(60000)] - public void ValidateClusterAuthWithGroupOid() + public async Task ValidateClusterAuthWithGroupOid() { var nodes = 2; var audience = Guid.NewGuid().ToString(); @@ -79,16 +80,15 @@ public void ValidateClusterAuthWithGroupOid() }; var authSettings = new AadAuthenticationSettings([appId], [audience], [issuer], new MockIssuerSigningTokenProvider(new List { tokenGenerator.SecurityKey }, context.logger), true); var token = tokenGenerator.CreateToken(tokenClaims, DateTime.Now.AddMinutes(10)); - ValidateConnectionsWithToken(groupIds.First(), token, nodes, authSettings); + await ValidateConnectionsWithToken(groupIds.First(), token, nodes, authSettings); } - private void ValidateConnectionsWithToken(string aclUsername, string token, int nodeCount, AadAuthenticationSettings authenticationSettings) + private async Task ValidateConnectionsWithToken(string aclUsername, string token, int nodeCount, AadAuthenticationSettings authenticationSettings) { var userCredential = new ServerCredential { user = aclUsername, IsAdmin = true, IsClearText = true }; var clientCredentials = new ServerCredential { user = aclUsername, password = token }; context.GenerateCredentials([userCredential]); - context.CreateInstances(nodeCount, useAcl: true, clusterCreds: clientCredentials, authenticationSettings: authenticationSettings); - + await context.CreateInstances(nodeCount, useAcl: true, clusterCreds: clientCredentials, authenticationSettings: authenticationSettings); context.CreateConnection(useTLS: false, clientCreds: clientCredentials); @@ -99,7 +99,6 @@ private void ValidateConnectionsWithToken(string aclUsername, string token, int var ex = Assert.Throws(() => context.clusterTestUtils.Authenticate(i, "randomUserId", clientCredentials.password, context.logger)); ClassicAssert.AreEqual("WRONGPASS Invalid username/password combination", ex.Message); } - } } } \ No newline at end of file diff --git a/test/Garnet.test.cluster/ClusterAuthCommsTests.cs b/test/Garnet.test.cluster/ClusterAuthCommsTests.cs index 2f26bcae7f..445181e0c0 100644 --- a/test/Garnet.test.cluster/ClusterAuthCommsTests.cs +++ b/test/Garnet.test.cluster/ClusterAuthCommsTests.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Net; +using System.Threading.Tasks; using Microsoft.Extensions.Logging; using NUnit.Framework; using NUnit.Framework.Legacy; @@ -33,7 +34,7 @@ public void TearDown() [Test, Order(1)] [Category("CLUSTER-AUTH"), CancelAfter(60000)] - public void ClusterBasicACLTest([Values] bool useDefaultUserForInterNodeComms) + public async Task ClusterBasicACLTest([Values] bool useDefaultUserForInterNodeComms) { var nodes = 6; @@ -43,12 +44,12 @@ public void ClusterBasicACLTest([Values] bool useDefaultUserForInterNodeComms) if (useDefaultUserForInterNodeComms) { // Create instances, feed generated acl file and use default user for cluster auth - context.CreateInstances(nodes, useAcl: true, clusterCreds: context.credManager.GetUserCredentials("default")); + await context.CreateInstances(nodes, useAcl: true, clusterCreds: context.credManager.GetUserCredentials("default")); } else { // Create instances, feed generated acl file and use admin user for cluster auth - context.CreateInstances(nodes, useAcl: true, clusterCreds: context.credManager.GetUserCredentials("admin")); + await context.CreateInstances(nodes, useAcl: true, clusterCreds: context.credManager.GetUserCredentials("admin")); } context.CreateConnection(useTLS: false, clientCreds: context.credManager.GetUserCredentials("admin")); @@ -65,7 +66,7 @@ public void ClusterBasicACLTest([Values] bool useDefaultUserForInterNodeComms) [Test, Order(2)] [Category("CLUSTER-AUTH"), CancelAfter(60000)] - public void ClusterStartupWithoutAuthCreds([Values] bool useDefaultUserForInterNodeComms) + public async Task ClusterStartupWithoutAuthCreds([Values] bool useDefaultUserForInterNodeComms) { var shards = 3; @@ -73,7 +74,7 @@ public void ClusterStartupWithoutAuthCreds([Values] bool useDefaultUserForInterN context.GenerateCredentials(); // Create instances but do not provide credentials through server options - context.CreateInstances(shards, useAcl: true); + await context.CreateInstances(shards, useAcl: true); // Connect as admin context.CreateConnection(clientCreds: context.credManager.GetUserCredentials("admin")); @@ -111,14 +112,14 @@ public void ClusterStartupWithoutAuthCreds([Values] bool useDefaultUserForInterN [Test, Order(3)] [Category("CLUSTER-AUTH"), CancelAfter(60000)] - public void ClusterReplicationAuth() + public async Task ClusterReplicationAuth() { var shards = 3; // Generate default ACL file context.GenerateCredentials(); // Create instances but do not provide credentials through server options - context.CreateInstances(shards, useAcl: true, enableAOF: true); + await context.CreateInstances(shards, useAcl: true, enableAOF: true); // Connect as admin context.CreateConnection(clientCreds: context.credManager.GetUserCredentials("admin")); @@ -178,10 +179,10 @@ public void ClusterReplicationAuth() [Test, Order(4)] [Category("CLUSTER-AUTH"), CancelAfter(60000)] - public void ClusterSimpleFailoverAuth() + public async Task ClusterSimpleFailoverAuth() { // Setup single primary populate and then attach replicas - ClusterReplicationAuth(); + await ClusterReplicationAuth(); context.ClusterFailoveSpinWait(replicaNodeIndex: 1, logger: context.logger); @@ -195,7 +196,7 @@ public void ClusterSimpleFailoverAuth() [Test, Order(4)] [Category("CLUSTER-AUTH"), CancelAfter(60000)] - public void ClusterSimpleACLReload() + public async Task ClusterSimpleACLReload() { ClusterStartupWithoutAuthCreds(useDefaultUserForInterNodeComms: true); @@ -214,9 +215,10 @@ public void ClusterSimpleACLReload() context.clusterTestUtils.AclLoad(1, logger: context.logger); // Restart node with new ACL file - context.nodes[0].Dispose(false); + await context.nodes[0].StopAsync(); + context.nodes[0].Dispose(); ; context.nodes[0] = context.CreateInstance(context.clusterTestUtils.GetEndPoint(0).Port, useAcl: true, cleanClusterConfig: false); - context.nodes[0].Start(); + await context.nodes[0].RunAsync(); context.CreateConnection(clientCreds: cc[0]); diff --git a/test/Garnet.test.cluster/ClusterConfigTests.cs b/test/Garnet.test.cluster/ClusterConfigTests.cs index 55c7b705fb..f0a2fe0bdb 100644 --- a/test/Garnet.test.cluster/ClusterConfigTests.cs +++ b/test/Garnet.test.cluster/ClusterConfigTests.cs @@ -4,8 +4,10 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading.Tasks; using Garnet.cluster; using Garnet.common; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using NUnit.Framework; using NUnit.Framework.Internal; @@ -62,7 +64,7 @@ public void ClusterConfigInitializesUnassignedWorkerTest() [Test, Order(2)] [Category("CLUSTER-CONFIG"), CancelAfter(1000)] - public void ClusterForgetAfterNodeRestartTest() + public async Task ClusterForgetAfterNodeRestartTest() { int nbInstances = 4; context.CreateInstances(nbInstances); @@ -70,9 +72,10 @@ public void ClusterForgetAfterNodeRestartTest() var (shards, slots) = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); // Restart node with new ACL file - context.nodes[0].Dispose(false); + await context.nodes[0].StopAsync(); + context.nodes[0].Dispose(); ; context.nodes[0] = context.CreateInstance(context.clusterTestUtils.GetEndPoint(0).Port, useAcl: true, cleanClusterConfig: false); - context.nodes[0].Start(); + await context.nodes[0].RunAsync(); context.CreateConnection(); var firstNode = context.nodes[0]; diff --git a/test/Garnet.test.cluster/ClusterManagementTests.cs b/test/Garnet.test.cluster/ClusterManagementTests.cs index dcaff8956b..2a1798e3a1 100644 --- a/test/Garnet.test.cluster/ClusterManagementTests.cs +++ b/test/Garnet.test.cluster/ClusterManagementTests.cs @@ -38,11 +38,11 @@ public void TearDown() [Test, Order(1)] [TestCase(0, 16383)] [TestCase(1234, 5678)] - public void ClusterSlotsTest(int startSlot, int endSlot) + public async Task ClusterSlotsTest(int startSlot, int endSlot) { var slotRanges = new List<(int, int)>[1]; slotRanges[0] = [(startSlot, endSlot)]; - context.CreateInstances(defaultShards); + await context.CreateInstances(defaultShards); context.CreateConnection(); _ = context.clusterTestUtils.SimpleSetupCluster(customSlotRanges: slotRanges, logger: context.logger); @@ -58,9 +58,9 @@ public void ClusterSlotsTest(int startSlot, int endSlot) } [Test, Order(2)] - public void ClusterSlotRangesTest() + public async Task ClusterSlotRangesTest() { - context.CreateInstances(defaultShards); + await context.CreateInstances(defaultShards); context.CreateConnection(); var slotRanges = new List<(int, int)>[3]; slotRanges[0] = [(5680, 6150), (12345, 14567)]; @@ -97,10 +97,10 @@ public void ClusterSlotRangesTest() } [Test, Order(3)] - public void ClusterForgetTest() + public async Task ClusterForgetTest() { var node_count = 4; - context.CreateInstances(node_count); + await context.CreateInstances(node_count); context.CreateConnection(); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(node_count, 0, logger: context.logger); @@ -127,10 +127,10 @@ public void ClusterForgetTest() } [Test, Order(4)] - public void ClusterResetTest() + public async Task ClusterResetTest() { var node_count = 4; - context.CreateInstances(node_count); + await context.CreateInstances(node_count); context.CreateConnection(); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(node_count, 0, logger: context.logger); @@ -172,10 +172,10 @@ public void ClusterResetTest() } [Test, Order(4)] - public void ClusterResetFailsForMasterWithKeysInSlotsTest() + public async Task ClusterResetFailsForMasterWithKeysInSlotsTest() { var node_count = 4; - context.CreateInstances(node_count); + await context.CreateInstances(node_count); context.CreateConnection(); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(node_count, 0, logger: context.logger); @@ -202,10 +202,10 @@ public void ClusterResetFailsForMasterWithKeysInSlotsTest() } [Test, Order(4)] - public void ClusterResetFailsForMasterWithKeysInSlotsObjectStoreTest() + public async Task ClusterResetFailsForMasterWithKeysInSlotsObjectStoreTest() { var node_count = 4; - context.CreateInstances(node_count); + await context.CreateInstances(node_count); context.CreateConnection(); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(node_count, 0, logger: context.logger); context.kvPairsObj = new Dictionary>(); @@ -229,10 +229,10 @@ public void ClusterResetFailsForMasterWithKeysInSlotsObjectStoreTest() } [Test, Order(4)] - public void ClusterResetAfterFLushAllTest() + public async Task ClusterResetAfterFLushAllTest() { var node_count = 4; - context.CreateInstances(node_count); + await context.CreateInstances(node_count); context.CreateConnection(); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(node_count, 0, logger: context.logger); context.kvPairsObj = new Dictionary>(); @@ -289,7 +289,7 @@ private void VerifyClusterResetFails(bool softReset = true) public async Task ClusterResetDisposesGossipConnections() { var node_count = 3; - context.CreateInstances(node_count, metricsSamplingFrequency: 1); + await context.CreateInstances(node_count, metricsSamplingFrequency: 1); context.CreateConnection(); var endpoints = context.clusterTestUtils.GetEndpoints(); for (int i = 0; i < endpoints.Length - 1; i++) @@ -323,10 +323,10 @@ private string GetStat(IServer server, string section, string statName) } [Test, Order(5)] - public void ClusterKeySlotTest() + public async Task ClusterKeySlotTest() { var node_count = 1; - context.CreateInstances(node_count); + await context.CreateInstances(node_count); context.CreateConnection(); (string, int)[] testCases = [("6e6bzswz8}", 7038), @@ -376,16 +376,16 @@ public void ClusterKeySlotTest() //[Test, Order(5)] //[Category("CLUSTER")] - public void ClusterRestartNodeDropGossip() + public async Task ClusterRestartNodeDropGossip() { var logger = context.loggerFactory.CreateLogger("ClusterRestartNodeDropGossip"); - context.CreateInstances(defaultShards); + await context.CreateInstances(defaultShards); context.CreateConnection(); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(logger: logger); var restartingNode = 2; // Dispose node and delete data - context.nodes[restartingNode].Dispose(deleteDir: true); + await context.nodes[restartingNode].RunAsync(); context.nodes[restartingNode] = context.CreateInstance( context.clusterTestUtils.GetEndPoint(restartingNode).Port, @@ -395,7 +395,7 @@ public void ClusterRestartNodeDropGossip() timeout: 60, gossipDelay: 1, cleanClusterConfig: false); - context.nodes[restartingNode].Start(); + await context.nodes[restartingNode].RunAsync(); context.CreateConnection(); Thread.Sleep(5000); @@ -409,10 +409,10 @@ public void ClusterRestartNodeDropGossip() } [Test, Order(7)] - public void ClusterClientList() + public async Task ClusterClientList() { const int NodeCount = 4; - context.CreateInstances(NodeCount, enableAOF: true, MainMemoryReplication: true, CommitFrequencyMs: -1); + await context.CreateInstances(NodeCount, enableAOF: true, MainMemoryReplication: true, CommitFrequencyMs: -1); context.CreateConnection(); _ = context.clusterTestUtils.SimpleSetupCluster(NodeCount / 2, 1, logger: context.logger); @@ -455,10 +455,10 @@ public void ClusterClientList() } [Test, Order(7)] - public void ClusterClientKill() + public async Task ClusterClientKill() { const int NodeCount = 4; - context.CreateInstances(NodeCount, enableAOF: true, MainMemoryReplication: true, CommitFrequencyMs: -1); + await context.CreateInstances(NodeCount, enableAOF: true, MainMemoryReplication: true, CommitFrequencyMs: -1); context.CreateConnection(); _ = context.clusterTestUtils.SimpleSetupCluster(NodeCount / 2, 1, logger: context.logger); @@ -470,12 +470,12 @@ public void ClusterClientKill() } [Test, Order(7)] - public void ClusterClientKillSlave() + public async Task ClusterClientKillSlave() { // Test SLAVE separately - it's equivalent to REPLICA, but needed for compatibility const int NodeCount = 4; - context.CreateInstances(NodeCount, enableAOF: true, MainMemoryReplication: true, CommitFrequencyMs: -1); + await context.CreateInstances(NodeCount, enableAOF: true, MainMemoryReplication: true, CommitFrequencyMs: -1); context.CreateConnection(); _ = context.clusterTestUtils.SimpleSetupCluster(NodeCount / 2, 1, logger: context.logger); @@ -485,10 +485,10 @@ public void ClusterClientKillSlave() } [Test, Order(8)] - public void FailoverBadOptions() + public async Task FailoverBadOptions() { var node_count = 4; - context.CreateInstances(node_count); + await context.CreateInstances(node_count); context.CreateConnection(); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(node_count, 0, logger: context.logger); @@ -520,10 +520,10 @@ public void FailoverBadOptions() } [Test, Order(9)] - public void ClusterFailoverBadOptions() + public async Task ClusterFailoverBadOptions() { var node_count = 4; - context.CreateInstances(node_count); + await context.CreateInstances(node_count); context.CreateConnection(); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(node_count, 0, logger: context.logger); @@ -555,10 +555,10 @@ public void ClusterFailoverBadOptions() } [Test, Order(10)] - public void ClusterSetSlotBadOptions() + public async Task ClusterSetSlotBadOptions() { var node_count = 4; - context.CreateInstances(node_count); + await context.CreateInstances(node_count); context.CreateConnection(); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(node_count, 0, logger: context.logger); diff --git a/test/Garnet.test.cluster/ClusterMigrateTLSTests.cs b/test/Garnet.test.cluster/ClusterMigrateTLSTests.cs index 85f47f96ab..5f07bb6033 100644 --- a/test/Garnet.test.cluster/ClusterMigrateTLSTests.cs +++ b/test/Garnet.test.cluster/ClusterMigrateTLSTests.cs @@ -1,12 +1,13 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +using System.Threading.Tasks; using NUnit.Framework; namespace Garnet.test.cluster { [TestFixture, NonParallelizable] - public unsafe class ClusterTLSMT + public class ClusterTLSMT { ClusterMigrateTests tests; @@ -26,57 +27,57 @@ public void TearDown() [Test, Order(1)] [Category("CLUSTER")] - public void ClusterTLSInitialize() - => tests.ClusterSimpleInitialize(); + public async Task ClusterTLSInitialize() + => await tests.ClusterSimpleInitialize(); [Test, Order(2)] [Category("CLUSTER")] - public void ClusterTLSSlotInfo() - => tests.ClusterSimpleSlotInfo(); + public async Task ClusterTLSSlotInfo() + => await tests.ClusterSimpleSlotInfo(); [Test, Order(3)] [Category("CLUSTER")] - public void ClusterTLSAddDelSlots() - => tests.ClusterAddDelSlots(); + public async Task ClusterTLSAddDelSlots() + => await tests.ClusterAddDelSlots(); [Test, Order(4)] [Category("CLUSTER")] - public void ClusterTLSSlotChangeStatus() - => tests.ClusterSlotChangeStatus(); + public async Task ClusterTLSSlotChangeStatus() + => await tests.ClusterSlotChangeStatus(); [Test, Order(5)] [Category("CLUSTER")] - public void ClusterTLSRedirectMessage() - => tests.ClusterRedirectMessage(); + public async Task ClusterTLSRedirectMessage() + => await tests.ClusterRedirectMessage(); [Test, Order(6)] [Category("CLUSTER")] - public void ClusterTLSMigrateSlots() - => tests.ClusterSimpleMigrateSlots(); + public async Task ClusterTLSMigrateSlots() + => await tests.ClusterSimpleMigrateSlots(); [Test, Order(7)] [Category("CLUSTER")] - public void ClusterTLSMigrateSlotsExpiry() - => tests.ClusterSimpleMigrateSlotsExpiry(); + public async Task ClusterTLSMigrateSlotsExpiry() + => await tests.ClusterSimpleMigrateSlotsExpiry(); [Test, Order(8)] [Category("CLUSTER")] - public void ClusterTLSMigrateSlotsWithObjects() - => tests.ClusterSimpleMigrateSlotsWithObjects(); + public async Task ClusterTLSMigrateSlotsWithObjects() + => await tests.ClusterSimpleMigrateSlotsWithObjects(); [Test, Order(9)] [Category("CLUSTER")] - public void ClusterTLSMigrateKeys() - => tests.ClusterSimpleMigrateKeys(); + public async Task ClusterTLSMigrateKeys() + => await tests.ClusterSimpleMigrateKeys(); [Test, Order(10)] [Category("CLUSTER")] - public void ClusterTLSMigrateKeysWithObjects() - => tests.ClusterSimpleMigrateKeysWithObjects(); + public async Task ClusterTLSMigrateKeysWithObjects() + => await tests.ClusterSimpleMigrateKeysWithObjects(); [Test, Order(11)] [Category("CLUSTER")] - public void ClusterTLSMigratetWithReadWrite() - => tests.ClusterSimpleMigrateWithReadWrite(); + public async Task ClusterTLSMigratetWithReadWrite() + => await tests.ClusterSimpleMigrateWithReadWrite(); } } \ No newline at end of file diff --git a/test/Garnet.test.cluster/ClusterMigrateTests.cs b/test/Garnet.test.cluster/ClusterMigrateTests.cs index 7ddc728d53..549beac2e3 100644 --- a/test/Garnet.test.cluster/ClusterMigrateTests.cs +++ b/test/Garnet.test.cluster/ClusterMigrateTests.cs @@ -18,36 +18,36 @@ namespace Garnet.test.cluster { [TestFixture(false), NonParallelizable] - public unsafe class ClusterMigrateTests(bool UseTLS) + public class ClusterMigrateTests(bool UseTLS) { const int testTimeout = 100000; - public (Action, string)[] GetUnitTests() + public (Task, string)[] GetUnitTests() { - (Action, string)[] x = + (Task, string)[] x = [ //1 - new(ClusterSimpleInitialize, "ClusterSimpleInitialize()"), + new(ClusterSimpleInitialize(), "ClusterSimpleInitialize()"), //2 - new(ClusterSimpleSlotInfo, "ClusterSimpleSlotInfo()"), + new(ClusterSimpleSlotInfo(), "ClusterSimpleSlotInfo()"), //3 - new(ClusterAddDelSlots, "ClusterAddDelSlots()"), + new(ClusterAddDelSlots(), "ClusterAddDelSlots()"), //4 - new(ClusterSlotChangeStatus, "ClusterSlotChangeStatus()"), + new(ClusterSlotChangeStatus(), "ClusterSlotChangeStatus()"), //5 - new(ClusterRedirectMessage, "ClusterRedirectMessage()"), + new(ClusterRedirectMessage(), "ClusterRedirectMessage()"), //6 - new(ClusterSimpleMigrateSlots, "ClusterSimpleMigrateSlots()"), + new(ClusterSimpleMigrateSlots(), "ClusterSimpleMigrateSlots()"), //7 - new(ClusterSimpleMigrateSlotsExpiry, "ClusterSimpleMigrateSlotsExpiry()"), + new(ClusterSimpleMigrateSlotsExpiry(), "ClusterSimpleMigrateSlotsExpiry()"), //8 - new(ClusterSimpleMigrateSlotsWithObjects, "ClusterSimpleMigrateSlotsWithObjects()"), + new(ClusterSimpleMigrateSlotsWithObjects(), "ClusterSimpleMigrateSlotsWithObjects()"), //9 - new(ClusterSimpleMigrateKeys, "ClusterSimpleMigrateKeys()"), + new(ClusterSimpleMigrateKeys(), "ClusterSimpleMigrateKeys()"), //10 - new(ClusterSimpleMigrateKeysWithObjects, "ClusterSimpleMigrateKeysWithObjects()"), + new(ClusterSimpleMigrateKeysWithObjects(), "ClusterSimpleMigrateKeysWithObjects()"), //11 - new(ClusterSimpleMigrateWithReadWrite, "ClusterSimpleMigrateWithReadWrite()"), + new(ClusterSimpleMigrateWithReadWrite(), "ClusterSimpleMigrateWithReadWrite()"), ]; return x; } @@ -234,9 +234,9 @@ private void CreateMultiSlotData( [Test, Order(1)] [Category("CLUSTER")] - public void ClusterSimpleInitialize() + public async Task ClusterSimpleInitialize() { - context.CreateInstances(defaultShards, useTLS: UseTLS); + await context.CreateInstances(defaultShards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); context.logger.LogDebug("0. ClusterSimpleInitialize started"); @@ -254,9 +254,9 @@ public void ClusterSimpleInitialize() [Test, Order(2)] [Category("CLUSTER")] - public void ClusterSimpleSlotInfo() + public async Task ClusterSimpleSlotInfo() { - context.CreateInstances(defaultShards, useTLS: UseTLS); + await context.CreateInstances(defaultShards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); context.logger.LogDebug("0. ClusterSimpleSlotInfoTest started"); @@ -283,9 +283,9 @@ public void ClusterSimpleSlotInfo() [Test, Order(3)] [Category("CLUSTER")] - public void ClusterAddDelSlots() + public async Task ClusterAddDelSlots() { - context.CreateInstances(defaultShards, useTLS: UseTLS); + await context.CreateInstances(defaultShards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); context.logger.LogDebug("0. ClusterAddDelSlotsTest started"); @@ -360,10 +360,10 @@ public void ClusterAddDelSlots() [Test, Order(4)] [Category("CLUSTER")] - public void ClusterSlotChangeStatus() + public async Task ClusterSlotChangeStatus() { context.logger.LogDebug("0. ClusterSlotChangeStatusTest started"); - context.CreateInstances(defaultShards, useTLS: UseTLS); + await context.CreateInstances(defaultShards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); var sourcePortIndex = 1; @@ -508,11 +508,11 @@ public void ClusterSlotChangeStatus() [Test, Order(5)] [Category("CLUSTER")] - public void ClusterRedirectMessage() + public async Task ClusterRedirectMessage() { context.logger.LogDebug("0. ClusterRedirectMessageTest started"); var Shards = 2; - context.CreateInstances(Shards, useTLS: UseTLS); + await context.CreateInstances(Shards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); _ = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); var key = Encoding.ASCII.GetBytes("{abc}0"); @@ -565,12 +565,12 @@ public void ClusterRedirectMessage() [Test, Order(6)] [Category("CLUSTER")] - public void ClusterSimpleMigrateSlots() + public async Task ClusterSimpleMigrateSlots() { context.logger.LogDebug("0. ClusterSimpleMigrateSlotsTest started"); var Port = TestUtils.Port; var Shards = defaultShards; - context.CreateInstances(Shards, useTLS: UseTLS); + await context.CreateInstances(Shards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); var (_, slots) = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); @@ -653,10 +653,10 @@ public void ClusterSimpleMigrateSlots() [Test, Order(7)] [Category("CLUSTER")] - public void ClusterSimpleMigrateSlotsExpiry() + public async Task ClusterSimpleMigrateSlotsExpiry() { context.logger.LogDebug("0. ClusterSimpleMigrateSlotsExpiryTest started"); - context.CreateInstances(defaultShards, useTLS: UseTLS); + await context.CreateInstances(defaultShards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); _ = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); @@ -839,12 +839,12 @@ private string DoZCOUNT(int nodeIndex, byte[] key, out int count, out string add [Test, Order(8)] [Category("CLUSTER")] - public void ClusterSimpleMigrateSlotsWithObjects() + public async Task ClusterSimpleMigrateSlotsWithObjects() { context.logger.LogDebug("0. ClusterSimpleMigrateSlotsWithObjectsTest started"); var Port = TestUtils.Port; var Shards = defaultShards; - context.CreateInstances(defaultShards, useTLS: UseTLS); + await context.CreateInstances(defaultShards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); var (_, slots) = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); @@ -895,10 +895,10 @@ public void ClusterSimpleMigrateSlotsWithObjects() [Test, Order(9)] [Category("CLUSTER")] - public void ClusterSimpleMigrateKeys() + public async Task ClusterSimpleMigrateKeys() { context.logger.LogDebug("0. ClusterSimpleMigrateKeysTest started"); - context.CreateInstances(defaultShards, useTLS: UseTLS); + await context.CreateInstances(defaultShards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); _ = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); @@ -1003,12 +1003,12 @@ public void ClusterSimpleMigrateKeys() [Test, Order(10)] [Category("CLUSTER")] - public void ClusterSimpleMigrateKeysWithObjects() + public async Task ClusterSimpleMigrateKeysWithObjects() { context.logger.LogDebug("0. ClusterSimpleMigrateKeysWithObjectsTest started"); var Port = TestUtils.Port; var Shards = defaultShards; - context.CreateInstances(Shards, useTLS: UseTLS); + await context.CreateInstances(Shards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); var (_, slots) = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); @@ -1231,11 +1231,11 @@ private void OperateOnSlotsTask(Dictionary> data [Test, Order(11)] [Category("CLUSTER")] - public void ClusterSimpleMigrateWithReadWrite() + public async Task ClusterSimpleMigrateWithReadWrite() { context.logger.LogDebug("0. ClusterSimpleMigrateTestWithReadWrite started"); var Shards = defaultShards; - context.CreateInstances(Shards, useTLS: UseTLS); + await context.CreateInstances(Shards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); _ = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); @@ -1291,9 +1291,9 @@ public void ClusterSimpleMigrateWithReadWrite() [Test, Order(12)] [Category("CLUSTER")] - public void ClusterSimpleTxn() + public async Task ClusterSimpleTxn() { - context.CreateInstances(defaultShards, useTLS: UseTLS); + await context.CreateInstances(defaultShards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); List<(string, ICollection)> commands = []; @@ -1337,11 +1337,11 @@ public void ClusterSimpleTxn() [Test, Order(13)] [Category("CLUSTER")] [TestCaseSource("_slotranges")] - public void ClusterSimpleMigrateSlotsRanges(List migrateRange) + public async Task ClusterSimpleMigrateSlotsRanges(List migrateRange) { context.logger.LogDebug("0. ClusterSimpleMigrateSlotsRanges started"); var Shards = defaultShards; - context.CreateInstances(Shards, useTLS: UseTLS); + await context.CreateInstances(Shards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); @@ -1389,11 +1389,11 @@ public void ClusterSimpleMigrateSlotsRanges(List migrateRange) [Test, Order(14)] [Category("CLUSTER")] [TestCaseSource("_slotranges")] - public void ClusterSimpleMigrateWithAuth(List migrateRange) + public async Task ClusterSimpleMigrateWithAuth(List migrateRange) { context.logger.LogDebug("0. ClusterSimpleMigrateWithAuth started"); var Shards = defaultShards; - context.CreateInstances(Shards, useTLS: UseTLS); + await context.CreateInstances(Shards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); @@ -1441,11 +1441,11 @@ public void ClusterSimpleMigrateWithAuth(List migrateRange) [Test, Order(15)] [Category("CLUSTER")] - public void ClusterAllowWritesDuringMigrateTest() + public async Task ClusterAllowWritesDuringMigrateTest() { context.logger.LogDebug("0. ClusterSimpleMigrateTestWithReadWrite started"); var Shards = defaultShards; - context.CreateInstances(Shards, useTLS: UseTLS); + await context.CreateInstances(Shards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); _ = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); @@ -1570,11 +1570,11 @@ Task WriteWorkload(IPEndPoint endPoint, byte[] key, int keyLen = 16) [Test, Order(16)] [Category("CLUSTER")] - public void ClusterMigrateForgetTest() + public async Task ClusterMigrateForgetTest() { context.logger.LogDebug("0. ClusterSimpleMigrateSlotsRanges started"); var Shards = defaultShards; - context.CreateInstances(Shards, useTLS: UseTLS); + await context.CreateInstances(Shards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); var (_, _) = context.clusterTestUtils.SimpleSetupCluster(logger: context.logger); @@ -1611,10 +1611,10 @@ public void ClusterMigrateForgetTest() [Test, Order(17)] [Category("CLUSTER")] - public void ClusterMigrateDataSlotsRange() + public async Task ClusterMigrateDataSlotsRange() { var Shards = 2; - context.CreateInstances(Shards, useTLS: UseTLS); + await context.CreateInstances(Shards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); var srcNodeIndex = 0; @@ -1706,10 +1706,10 @@ public void ClusterMigrateIncreasingPayload([Values] bool expiration, [Values] b ClusterMigrateExpirationWithVaryingPayload(expiration, data); } - private void ClusterMigrateExpirationWithVaryingPayload(bool expiration, List<(byte[], byte[])> data) + private async void ClusterMigrateExpirationWithVaryingPayload(bool expiration, List<(byte[], byte[])> data) { var Shards = 2; - context.CreateInstances(Shards, useTLS: UseTLS); + await context.CreateInstances(Shards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); var srcNodeIndex = 0; @@ -1777,14 +1777,14 @@ private void ClusterMigrateExpirationWithVaryingPayload(bool expiration, List<(b [Order(20), CancelAfter(testTimeout)] [TestCase(true)] [TestCase(false)] - public void ClusterMigrateSlotWalk(bool slots, CancellationToken cancellationToken) + public async Task ClusterMigrateSlotWalk(bool slots, CancellationToken cancellationToken) { var sourceNode = 0; var shards = 5; var targetNode = shards - 1; var slotCount = 10; - SetupInstances(sourceNode, out var nodeIds, out var nodeEndpoints); + var (nodeIds, nodeEndpoints) = await SetupInstances(sourceNode); for (var slot = 0; slot < slotCount; slot++) { @@ -1884,9 +1884,12 @@ void MigrateSlots() ValidateConfig(); - void SetupInstances(int sourceNode, out string[] nodeIds, out IPEndPoint[] nodeEndpoints) + async Task<(string[] nodeIds, IPEndPoint[] nodeEndpoints)> SetupInstances(int sourceNode) { - context.CreateInstances(shards, useTLS: UseTLS); + string[] nodeIds = null; + IPEndPoint[] nodeEndpoints = null; + + await context.CreateInstances(shards, useTLS: UseTLS); context.CreateConnection(useTLS: UseTLS); // Assign all slots to first node @@ -1912,6 +1915,8 @@ void SetupInstances(int sourceNode, out string[] nodeIds, out IPEndPoint[] nodeE nodeEndpoints = new IPEndPoint[shards]; for (var i = 0; i < shards; i++) nodeEndpoints[i] = context.clusterTestUtils.GetEndPoint(i); + + return (nodeIds, nodeEndpoints); } void ValidateConfig() diff --git a/test/Garnet.test.cluster/ClusterNegativeTests.cs b/test/Garnet.test.cluster/ClusterNegativeTests.cs index 71b2ac8a76..a5734f188b 100644 --- a/test/Garnet.test.cluster/ClusterNegativeTests.cs +++ b/test/Garnet.test.cluster/ClusterNegativeTests.cs @@ -8,6 +8,7 @@ using System.Net.Sockets; using System.Text; using System.Threading; +using System.Threading.Tasks; using Microsoft.Extensions.Logging; using NUnit.Framework; using NUnit.Framework.Legacy; @@ -75,9 +76,9 @@ public void TearDown() [TestCase("BEGIN_REPLICA_RECOVER", new int[] { 0, 1, 2, 3, 4, 5, 6, 8, 9 })] [TestCase("FAILSTOPWRITES", new int[] { 0, 2, 3, 4 })] [TestCase("FAILREPLICATIONOFFSET", new int[] { 0, 2, 3, 4 })] - public void ClusterCommandWrongParameters(string subcommand, params int[] invalidCount) + public async Task ClusterCommandWrongParameters(string subcommand, params int[] invalidCount) { - context.CreateInstances(1); + await context.CreateInstances(1); using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp); socket.NoDelay = true; @@ -113,7 +114,7 @@ public void ClusterCommandWrongParameters(string subcommand, params int[] invali [TestCase(10240)] public void ClusterAddSlotsPartialPackage(int chunkSize) { - context.CreateInstances(1); + context.CreateInstances(1).GetAwaiter().GetResult(); using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp); socket.NoDelay = true; socket.Connect(IPAddress.Loopback, 7000); diff --git a/test/Garnet.test.cluster/ClusterRedirectTests.cs b/test/Garnet.test.cluster/ClusterRedirectTests.cs index cdf6607b01..f550eebd6a 100644 --- a/test/Garnet.test.cluster/ClusterRedirectTests.cs +++ b/test/Garnet.test.cluster/ClusterRedirectTests.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading.Tasks; using Garnet.common; using Microsoft.Extensions.Logging; using NUnit.Framework; @@ -12,7 +13,7 @@ namespace Garnet.test.cluster { [TestFixture, NonParallelizable] - public unsafe class ClusterRedirectTests + public class ClusterRedirectTests { ClusterTestContext context; @@ -638,13 +639,13 @@ private void SendToMigratingNode( [Test, Order(1)] [Category("CLUSTER")] - public void ClusterSingleKeyRedirectionTests() + public async Task ClusterSingleKeyRedirectionTests() { context.logger.LogDebug("0. ClusterSingleKeyRedirectionTests started"); var Port = ClusterTestContext.Port; var Shards = context.defaultShards; - context.CreateInstances(Shards, cleanClusterConfig: true); + await context.CreateInstances(Shards, cleanClusterConfig: true); context.CreateConnection(); var connections = ClusterTestUtils.CreateLightRequestConnections(Enumerable.Range(Port, Shards).ToArray()); @@ -703,13 +704,13 @@ public void ClusterSingleKeyRedirectionTests() [Test, Order(2)] [Category("CLUSTER")] - public void ClusterMultiKeyRedirectionTests() + public async Task ClusterMultiKeyRedirectionTests() { context.logger.LogDebug("0. ClusterMultiKeyRedirectionTests started"); var Port = ClusterTestContext.Port; var Shards = context.defaultShards; - context.CreateInstances(Shards, cleanClusterConfig: true); + await context.CreateInstances(Shards, cleanClusterConfig: true); context.CreateConnection(); var connections = ClusterTestUtils.CreateLightRequestConnections(Enumerable.Range(Port, Shards).ToArray()); diff --git a/test/Garnet.test.cluster/ClusterReplicationTLSTests.cs b/test/Garnet.test.cluster/ClusterReplicationTLSTests.cs index 766819b0ec..0ced891586 100644 --- a/test/Garnet.test.cluster/ClusterReplicationTLSTests.cs +++ b/test/Garnet.test.cluster/ClusterReplicationTLSTests.cs @@ -1,12 +1,13 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +using System.Threading.Tasks; using NUnit.Framework; namespace Garnet.test.cluster { [TestFixture, NonParallelizable] - public unsafe class ClusterTLSRT + public class ClusterTLSRT { ClusterReplicationTests tests; @@ -26,47 +27,47 @@ public void TearDown() [Test, Order(1)] [Category("REPLICATION")] - public void ClusterTLSR([Values] bool disableObjects) - => tests.ClusterSRTest(disableObjects); + public async Task ClusterTLSR([Values] bool disableObjects) + => await tests.ClusterSRTest(disableObjects); [Test, Order(2)] [Category("REPLICATION")] - public void ClusterTLSRCheckpointRestartSecondary([Values] bool performRMW, [Values] bool disableObjects) - => tests.ClusterSRNoCheckpointRestartSecondary(performRMW, disableObjects); + public async Task ClusterTLSRCheckpointRestartSecondary([Values] bool performRMW, [Values] bool disableObjects) + => await tests.ClusterSRNoCheckpointRestartSecondary(performRMW, disableObjects); [Test, Order(3)] [Category("REPLICATION")] - public void ClusterTLSRPrimaryCheckpoint([Values] bool performRMW, [Values] bool disableObjects) - => tests.ClusterSRPrimaryCheckpoint(performRMW, disableObjects); + public async Task ClusterTLSRPrimaryCheckpoint([Values] bool performRMW, [Values] bool disableObjects) + => await tests.ClusterSRPrimaryCheckpoint(performRMW, disableObjects); [Test, Order(4)] [Category("REPLICATION")] - public void ClusterTLSRPrimaryCheckpointRetrieve([Values] bool performRMW, [Values] bool disableObjects, [Values] bool lowMemory, [Values] bool manySegments) - => tests.ClusterSRPrimaryCheckpointRetrieve(performRMW, disableObjects, lowMemory, manySegments); + public async Task ClusterTLSRPrimaryCheckpointRetrieve([Values] bool performRMW, [Values] bool disableObjects, [Values] bool lowMemory, [Values] bool manySegments) + => await tests.ClusterSRPrimaryCheckpointRetrieve(performRMW, disableObjects, lowMemory, manySegments); [Test, Order(5)] [Category("REPLICATION")] - public void ClusterTLSCheckpointRetrieveDisableStorageTier([Values] bool performRMW, [Values] bool disableObjects) - => tests.ClusterCheckpointRetrieveDisableStorageTier(performRMW, disableObjects); + public async Task ClusterTLSCheckpointRetrieveDisableStorageTier([Values] bool performRMW, [Values] bool disableObjects) + => await tests.ClusterCheckpointRetrieveDisableStorageTier(performRMW, disableObjects); [Test, Order(6)] [Category("REPLICATION")] - public void ClusterTLSRAddReplicaAfterPrimaryCheckpoint([Values] bool performRMW, [Values] bool disableObjects, [Values] bool lowMemory) - => tests.ClusterSRAddReplicaAfterPrimaryCheckpoint(performRMW, disableObjects, lowMemory); + public async Task ClusterTLSRAddReplicaAfterPrimaryCheckpoint([Values] bool performRMW, [Values] bool disableObjects, [Values] bool lowMemory) + => await tests.ClusterSRAddReplicaAfterPrimaryCheckpoint(performRMW, disableObjects, lowMemory); [Test, Order(7)] [Category("REPLICATION")] - public void ClusterTLSRPrimaryRestart([Values] bool performRMW, [Values] bool disableObjects) - => tests.ClusterSRPrimaryRestart(performRMW, disableObjects); + public async Task ClusterTLSRPrimaryRestart([Values] bool performRMW, [Values] bool disableObjects) + => await tests.ClusterSRPrimaryRestart(performRMW, disableObjects); [Test, Order(8)] [Category("REPLICATION")] - public void ClusterTLSRRedirectWrites() - => tests.ClusterSRRedirectWrites(); + public async Task ClusterTLSRRedirectWrites() + => await tests.ClusterSRRedirectWrites(); [Test, Order(9)] [Category("REPLICATION")] - public void ClusterTLSRReplicaOfTest([Values] bool performRMW) - => tests.ClusterSRReplicaOfTest(performRMW); + public async Task ClusterTLSRReplicaOfTest([Values] bool performRMW) + => await tests.ClusterSRReplicaOfTest(performRMW); } } \ No newline at end of file diff --git a/test/Garnet.test.cluster/ClusterReplicationTests.cs b/test/Garnet.test.cluster/ClusterReplicationTests.cs index cdccac8a3c..52d986dcde 100644 --- a/test/Garnet.test.cluster/ClusterReplicationTests.cs +++ b/test/Garnet.test.cluster/ClusterReplicationTests.cs @@ -9,6 +9,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using Azure.Core; using Microsoft.Extensions.Logging; using NUnit.Framework; using NUnit.Framework.Legacy; @@ -19,61 +20,61 @@ namespace Garnet.test.cluster [TestFixture(false, false), NonParallelizable] public class ClusterReplicationTests(bool UseTLS = false, bool asyncReplay = false) { - public (Action, string)[] GetUnitTests() + public (Task, string)[] GetUnitTests() { - var x = new (Action, string)[39]; + var x = new (Task, string)[39]; //1 - x[0] = new(() => ClusterSRTest(true), "ClusterSRTest(true)"); - x[1] = new(() => ClusterSRTest(false), "ClusterSRTest(false)"); + x[0] = new(ClusterSRTest(true), "ClusterSRTest(true)"); + x[1] = new(ClusterSRTest(false), "ClusterSRTest(false)"); //2 - x[2] = new(() => ClusterSRNoCheckpointRestartSecondary(false, false), "ClusterSRNoCheckpointRestartSecondary(false, false)"); - x[3] = new(() => ClusterSRNoCheckpointRestartSecondary(false, true), "ClusterSRNoCheckpointRestartSecondary(false, true)"); - x[4] = new(() => ClusterSRNoCheckpointRestartSecondary(true, false), "ClusterSRNoCheckpointRestartSecondary(true, false)"); - x[5] = new(() => ClusterSRNoCheckpointRestartSecondary(true, true), "ClusterSRNoCheckpointRestartSecondary(true, true)"); + x[2] = new(ClusterSRNoCheckpointRestartSecondary(false, false), "ClusterSRNoCheckpointRestartSecondary(false, false)"); + x[3] = new(ClusterSRNoCheckpointRestartSecondary(false, true), "ClusterSRNoCheckpointRestartSecondary(false, true)"); + x[4] = new(ClusterSRNoCheckpointRestartSecondary(true, false), "ClusterSRNoCheckpointRestartSecondary(true, false)"); + x[5] = new(ClusterSRNoCheckpointRestartSecondary(true, true), "ClusterSRNoCheckpointRestartSecondary(true, true)"); //3 - x[6] = new(() => ClusterSRPrimaryCheckpoint(false, false), "ClusterSRPrimaryCheckpoint(false, false)"); - x[7] = new(() => ClusterSRPrimaryCheckpoint(false, true), "ClusterSRPrimaryCheckpoint(false, true)"); - x[8] = new(() => ClusterSRPrimaryCheckpoint(true, false), "ClusterSRPrimaryCheckpoint(true, false)"); - x[9] = new(() => ClusterSRPrimaryCheckpoint(true, true), "ClusterSRPrimaryCheckpoint(true, true)"); + x[6] = new(ClusterSRPrimaryCheckpoint(false, false), "ClusterSRPrimaryCheckpoint(false, false)"); + x[7] = new(ClusterSRPrimaryCheckpoint(false, true), "ClusterSRPrimaryCheckpoint(false, true)"); + x[8] = new(ClusterSRPrimaryCheckpoint(true, false), "ClusterSRPrimaryCheckpoint(true, false)"); + x[9] = new(ClusterSRPrimaryCheckpoint(true, true), "ClusterSRPrimaryCheckpoint(true, true)"); //4 - x[10] = new(() => ClusterSRPrimaryCheckpointRetrieve(false, false, false, false), "ClusterSRPrimaryCheckpointRetrieve(false, false, false, false)"); - x[11] = new(() => ClusterSRPrimaryCheckpointRetrieve(false, false, false, true), "ClusterSRPrimaryCheckpointRetrieve(false, false, false, true)"); - x[12] = new(() => ClusterSRPrimaryCheckpointRetrieve(false, true, false, false), "ClusterSRPrimaryCheckpointRetrieve(false, true, false, false)"); - x[13] = new(() => ClusterSRPrimaryCheckpointRetrieve(false, true, false, true), "ClusterSRPrimaryCheckpointRetrieve(false, true, false, true)"); - x[14] = new(() => ClusterSRPrimaryCheckpointRetrieve(true, false, false, false), "ClusterSRPrimaryCheckpointRetrieve(true, false, false, false)"); - x[15] = new(() => ClusterSRPrimaryCheckpointRetrieve(true, false, false, true), "ClusterSRPrimaryCheckpointRetrieve(true, false, false, true)"); - x[16] = new(() => ClusterSRPrimaryCheckpointRetrieve(true, true, false, false), "ClusterSRPrimaryCheckpointRetrieve(true, true, false, false)"); - x[17] = new(() => ClusterSRPrimaryCheckpointRetrieve(true, true, false, true), "ClusterSRPrimaryCheckpointRetrieve(true, true, false, true)"); - x[18] = new(() => ClusterSRPrimaryCheckpointRetrieve(false, false, true, false), "ClusterSRPrimaryCheckpointRetrieve(false, false, false)"); - x[19] = new(() => ClusterSRPrimaryCheckpointRetrieve(false, false, true, true), "ClusterSRPrimaryCheckpointRetrieve(false, false, true)"); - x[20] = new(() => ClusterSRPrimaryCheckpointRetrieve(false, true, true, false), "ClusterSRPrimaryCheckpointRetrieve(false, true, true, false)"); - x[21] = new(() => ClusterSRPrimaryCheckpointRetrieve(false, true, true, true), "ClusterSRPrimaryCheckpointRetrieve(false, true, true, true)"); - x[22] = new(() => ClusterSRPrimaryCheckpointRetrieve(true, false, true, false), "ClusterSRPrimaryCheckpointRetrieve(true, false, true, false)"); - x[23] = new(() => ClusterSRPrimaryCheckpointRetrieve(true, false, true, true), "ClusterSRPrimaryCheckpointRetrieve(true, false, true, true)"); - x[24] = new(() => ClusterSRPrimaryCheckpointRetrieve(true, true, true, false), "ClusterSRPrimaryCheckpointRetrieve(true, true, true, false)"); - x[25] = new(() => ClusterSRPrimaryCheckpointRetrieve(true, true, true, true), "ClusterSRPrimaryCheckpointRetrieve(true, true, true, true)"); + x[10] = new(ClusterSRPrimaryCheckpointRetrieve(false, false, false, false), "ClusterSRPrimaryCheckpointRetrieve(false, false, false, false)"); + x[11] = new(ClusterSRPrimaryCheckpointRetrieve(false, false, false, true), "ClusterSRPrimaryCheckpointRetrieve(false, false, false, true)"); + x[12] = new(ClusterSRPrimaryCheckpointRetrieve(false, true, false, false), "ClusterSRPrimaryCheckpointRetrieve(false, true, false, false)"); + x[13] = new(ClusterSRPrimaryCheckpointRetrieve(false, true, false, true), "ClusterSRPrimaryCheckpointRetrieve(false, true, false, true)"); + x[14] = new(ClusterSRPrimaryCheckpointRetrieve(true, false, false, false), "ClusterSRPrimaryCheckpointRetrieve(true, false, false, false)"); + x[15] = new(ClusterSRPrimaryCheckpointRetrieve(true, false, false, true), "ClusterSRPrimaryCheckpointRetrieve(true, false, false, true)"); + x[16] = new(ClusterSRPrimaryCheckpointRetrieve(true, true, false, false), "ClusterSRPrimaryCheckpointRetrieve(true, true, false, false)"); + x[17] = new(ClusterSRPrimaryCheckpointRetrieve(true, true, false, true), "ClusterSRPrimaryCheckpointRetrieve(true, true, false, true)"); + x[18] = new(ClusterSRPrimaryCheckpointRetrieve(false, false, true, false), "ClusterSRPrimaryCheckpointRetrieve(false, false, false)"); + x[19] = new(ClusterSRPrimaryCheckpointRetrieve(false, false, true, true), "ClusterSRPrimaryCheckpointRetrieve(false, false, true)"); + x[20] = new(ClusterSRPrimaryCheckpointRetrieve(false, true, true, false), "ClusterSRPrimaryCheckpointRetrieve(false, true, true, false)"); + x[21] = new(ClusterSRPrimaryCheckpointRetrieve(false, true, true, true), "ClusterSRPrimaryCheckpointRetrieve(false, true, true, true)"); + x[22] = new(ClusterSRPrimaryCheckpointRetrieve(true, false, true, false), "ClusterSRPrimaryCheckpointRetrieve(true, false, true, false)"); + x[23] = new(ClusterSRPrimaryCheckpointRetrieve(true, false, true, true), "ClusterSRPrimaryCheckpointRetrieve(true, false, true, true)"); + x[24] = new(ClusterSRPrimaryCheckpointRetrieve(true, true, true, false), "ClusterSRPrimaryCheckpointRetrieve(true, true, true, false)"); + x[25] = new(ClusterSRPrimaryCheckpointRetrieve(true, true, true, true), "ClusterSRPrimaryCheckpointRetrieve(true, true, true, true)"); //5 - x[26] = new(() => ClusterSRAddReplicaAfterPrimaryCheckpoint(false, false, false), "ClusterSRAddReplicaAfterPrimaryCheckpoint(false, false, false)"); - x[27] = new(() => ClusterSRAddReplicaAfterPrimaryCheckpoint(false, false, true), "ClusterSRAddReplicaAfterPrimaryCheckpoint(false, false, true)"); - x[28] = new(() => ClusterSRAddReplicaAfterPrimaryCheckpoint(false, true, false), "ClusterSRAddReplicaAfterPrimaryCheckpoint(false, true, false)"); - x[29] = new(() => ClusterSRAddReplicaAfterPrimaryCheckpoint(false, true, true), "ClusterSRAddReplicaAfterPrimaryCheckpoint(false, true, true)"); - x[30] = new(() => ClusterSRAddReplicaAfterPrimaryCheckpoint(true, false, false), "ClusterSRAddReplicaAfterPrimaryCheckpoint(true, false, false)"); - x[31] = new(() => ClusterSRAddReplicaAfterPrimaryCheckpoint(true, false, true), "ClusterSRAddReplicaAfterPrimaryCheckpoint(true, false, true)"); - x[32] = new(() => ClusterSRAddReplicaAfterPrimaryCheckpoint(true, true, false), "ClusterSRAddReplicaAfterPrimaryCheckpoint(true, true, false)"); - x[33] = new(() => ClusterSRAddReplicaAfterPrimaryCheckpoint(true, true, true), "ClusterSRAddReplicaAfterPrimaryCheckpoint(true, true, true)"); + x[26] = new(ClusterSRAddReplicaAfterPrimaryCheckpoint(false, false, false), "ClusterSRAddReplicaAfterPrimaryCheckpoint(false, false, false)"); + x[27] = new(ClusterSRAddReplicaAfterPrimaryCheckpoint(false, false, true), "ClusterSRAddReplicaAfterPrimaryCheckpoint(false, false, true)"); + x[28] = new(ClusterSRAddReplicaAfterPrimaryCheckpoint(false, true, false), "ClusterSRAddReplicaAfterPrimaryCheckpoint(false, true, false)"); + x[29] = new(ClusterSRAddReplicaAfterPrimaryCheckpoint(false, true, true), "ClusterSRAddReplicaAfterPrimaryCheckpoint(false, true, true)"); + x[30] = new(ClusterSRAddReplicaAfterPrimaryCheckpoint(true, false, false), "ClusterSRAddReplicaAfterPrimaryCheckpoint(true, false, false)"); + x[31] = new(ClusterSRAddReplicaAfterPrimaryCheckpoint(true, false, true), "ClusterSRAddReplicaAfterPrimaryCheckpoint(true, false, true)"); + x[32] = new(ClusterSRAddReplicaAfterPrimaryCheckpoint(true, true, false), "ClusterSRAddReplicaAfterPrimaryCheckpoint(true, true, false)"); + x[33] = new(ClusterSRAddReplicaAfterPrimaryCheckpoint(true, true, true), "ClusterSRAddReplicaAfterPrimaryCheckpoint(true, true, true)"); //6 - x[34] = new(() => ClusterSRPrimaryRestart(false, false), "ClusterSRPrimaryRestart(false, false)"); - x[35] = new(() => ClusterSRPrimaryRestart(false, true), "ClusterSRPrimaryRestart(false, true)"); - x[36] = new(() => ClusterSRPrimaryRestart(true, false), "ClusterSRPrimaryRestart(true, false)"); - x[37] = new(() => ClusterSRPrimaryRestart(true, true), "ClusterSRPrimaryRestart(true, true)"); + x[34] = new(ClusterSRPrimaryRestart(false, false), "ClusterSRPrimaryRestart(false, false)"); + x[35] = new(ClusterSRPrimaryRestart(false, true), "ClusterSRPrimaryRestart(false, true)"); + x[36] = new(ClusterSRPrimaryRestart(true, false), "ClusterSRPrimaryRestart(true, false)"); + x[37] = new(ClusterSRPrimaryRestart(true, true), "ClusterSRPrimaryRestart(true, true)"); //7 - x[38] = new(ClusterSRRedirectWrites, "ClusterSRRedirectWrites()"); + x[38] = new(ClusterSRRedirectWrites(), "ClusterSRRedirectWrites()"); return x; } @@ -105,13 +106,13 @@ public void TearDown() [Test, Order(1)] [Category("REPLICATION")] - public void ClusterSRTest([Values] bool disableObjects) + public async Task ClusterSRTest([Values] bool disableObjects) { var replica_count = 1;// Per primary var primary_count = 1; var nodes_count = primary_count + primary_count * replica_count; ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, disableObjects: disableObjects, enableAOF: true, useTLS: useTLS); + await context.CreateInstances(nodes_count, disableObjects: disableObjects, enableAOF: true, useTLS: useTLS); context.CreateConnection(useTLS: useTLS); var (shards, _) = context.clusterTestUtils.SimpleSetupCluster(primary_count, replica_count, logger: context.logger); @@ -142,13 +143,13 @@ public void ClusterSRTest([Values] bool disableObjects) [Test, Order(2)] [Category("REPLICATION")] - public void ClusterSRNoCheckpointRestartSecondary([Values] bool performRMW, [Values] bool disableObjects) + public async Task ClusterSRNoCheckpointRestartSecondary([Values] bool performRMW, [Values] bool disableObjects) { var replica_count = 1;// Per primary var primary_count = 1; var nodes_count = primary_count + (primary_count * replica_count); ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, disableObjects: disableObjects, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, disableObjects: disableObjects, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); var (shards, _) = context.clusterTestUtils.SimpleSetupCluster(primary_count, replica_count, logger: context.logger); @@ -179,7 +180,8 @@ public void ClusterSRNoCheckpointRestartSecondary([Values] bool performRMW, [Val context.ValidateKVCollectionAgainstReplica(ref context.kvPairs, 1); // Shutdown secondary - context.nodes[1].Dispose(false); + await context.nodes[1].StopAsync(); + context.nodes[1].Dispose(); Thread.Sleep(TimeSpan.FromSeconds(2)); @@ -198,7 +200,7 @@ public void ClusterSRNoCheckpointRestartSecondary([Values] bool performRMW, [Val timeout: timeout, useTLS: useTLS, cleanClusterConfig: false); - context.nodes[1].Start(); + await context.nodes[1].RunAsync(); context.CreateConnection(useTLS: useTLS); // Validate synchronization was success @@ -208,13 +210,13 @@ public void ClusterSRNoCheckpointRestartSecondary([Values] bool performRMW, [Val [Test, Order(3)] [Category("REPLICATION")] - public void ClusterSRPrimaryCheckpoint([Values] bool performRMW, [Values] bool disableObjects) + public async Task ClusterSRPrimaryCheckpoint([Values] bool performRMW, [Values] bool disableObjects) { var replica_count = 1;// Per primary var primary_count = 1; var nodes_count = primary_count + (primary_count * replica_count); ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, disableObjects: disableObjects, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, disableObjects: disableObjects, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); var (shards, _) = context.clusterTestUtils.SimpleSetupCluster(primary_count, replica_count, logger: context.logger); @@ -253,7 +255,8 @@ public void ClusterSRPrimaryCheckpoint([Values] bool performRMW, [Values] bool d context.clusterTestUtils.WaitCheckpoint(1, replicaLastSaveTime, logger: context.logger); // Shutdown secondary - context.nodes[1].Dispose(false); + await context.nodes[1].StopAsync(); + context.nodes[1].Dispose(); ; Thread.Sleep(TimeSpan.FromSeconds(2)); // New insert @@ -272,7 +275,7 @@ public void ClusterSRPrimaryCheckpoint([Values] bool performRMW, [Values] bool d useTLS: useTLS, cleanClusterConfig: false, asyncReplay: asyncReplay); - context.nodes[1].Start(); + await context.nodes[1].RunAsync(); context.CreateConnection(useTLS: useTLS); for (int i = 1; i < replica_count; i++) context.clusterTestUtils.WaitForReplicaRecovery(i, context.logger); @@ -285,24 +288,24 @@ public void ClusterSRPrimaryCheckpoint([Values] bool performRMW, [Values] bool d [Test, Order(4)] [Category("REPLICATION")] - public void ClusterCheckpointRetrieveDisableStorageTier([Values] bool performRMW, [Values] bool disableObjects) + public async Task ClusterCheckpointRetrieveDisableStorageTier([Values] bool performRMW, [Values] bool disableObjects) { - ClusterSRPrimaryCheckpointRetrieve(performRMW, disableObjects, false, false, true, false); + await ClusterSRPrimaryCheckpointRetrieve(performRMW, disableObjects, false, false, true, false); } [Test, Order(5)] [Category("REPLICATION")] - public void ClusterCheckpointRetrieveDelta([Values] bool performRMW) + public async Task ClusterCheckpointRetrieveDelta([Values] bool performRMW) { - ClusterSRPrimaryCheckpointRetrieve(performRMW, true, false, false, false, true); + await ClusterSRPrimaryCheckpointRetrieve(performRMW, true, false, false, false, true); } [Test, Order(6)] [Category("REPLICATION")] - public void ClusterSRPrimaryCheckpointRetrieve([Values] bool performRMW, [Values] bool disableObjects, [Values] bool lowMemory, [Values] bool manySegments) - => ClusterSRPrimaryCheckpointRetrieve(performRMW: performRMW, disableObjects: disableObjects, lowMemory: lowMemory, manySegments: manySegments, false, false); + public async Task ClusterSRPrimaryCheckpointRetrieve([Values] bool performRMW, [Values] bool disableObjects, [Values] bool lowMemory, [Values] bool manySegments) + => await ClusterSRPrimaryCheckpointRetrieve(performRMW: performRMW, disableObjects: disableObjects, lowMemory: lowMemory, manySegments: manySegments, false, false); - void ClusterSRPrimaryCheckpointRetrieve(bool performRMW, bool disableObjects, bool lowMemory, bool manySegments, bool disableStorageTier, bool incrementalSnapshots) + async Task ClusterSRPrimaryCheckpointRetrieve(bool performRMW, bool disableObjects, bool lowMemory, bool manySegments, bool disableStorageTier, bool incrementalSnapshots) { // Test many segments on or off with lowMemory manySegments = lowMemory && manySegments; @@ -313,7 +316,7 @@ void ClusterSRPrimaryCheckpointRetrieve(bool performRMW, bool disableObjects, bo var primary_count = 1; var nodes_count = primary_count + primary_count * replica_count; ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, disableObjects: disableObjects, lowMemory: lowMemory, SegmentSize: manySegments ? "4k" : "1g", DisableStorageTier: disableStorageTier, EnableIncrementalSnapshots: incrementalSnapshots, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, disableObjects: disableObjects, lowMemory: lowMemory, SegmentSize: manySegments ? "4k" : "1g", DisableStorageTier: disableStorageTier, EnableIncrementalSnapshots: incrementalSnapshots, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); var (shards, _) = context.clusterTestUtils.SimpleSetupCluster(primary_count, replica_count, logger: context.logger); @@ -335,7 +338,8 @@ void ClusterSRPrimaryCheckpointRetrieve(bool performRMW, bool disableObjects, bo context.kvPairsObj = []; context.logger?.LogTrace("Test disposing node 1"); - context.nodes[1].Dispose(false); + await context.nodes[1].StopAsync(); + context.nodes[1].Dispose(); ; Thread.Sleep(TimeSpan.FromSeconds(1)); // Populate Primary @@ -371,7 +375,7 @@ void ClusterSRPrimaryCheckpointRetrieve(bool performRMW, bool disableObjects, bo SegmentSize: manySegments ? "4k" : "1g", DisableStorageTier: disableStorageTier, asyncReplay: asyncReplay); - context.nodes[replicaIndex].Start(); + await context.nodes[replicaIndex].RunAsync(); context.CreateConnection(useTLS: useTLS); context.clusterTestUtils.WaitForReplicaAofSync(primaryIndex, replicaIndex, context.logger); @@ -383,13 +387,13 @@ void ClusterSRPrimaryCheckpointRetrieve(bool performRMW, bool disableObjects, bo [Test, Order(7)] [Category("REPLICATION")] - public void ClusterSRAddReplicaAfterPrimaryCheckpoint([Values] bool performRMW, [Values] bool disableObjects, [Values] bool lowMemory) + public async Task ClusterSRAddReplicaAfterPrimaryCheckpoint([Values] bool performRMW, [Values] bool disableObjects, [Values] bool lowMemory) { var replica_count = 1;// Per primary var primary_count = 1; var nodes_count = primary_count + (primary_count * replica_count); ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, tryRecover: true, disableObjects: disableObjects, lowMemory: lowMemory, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, tryRecover: true, disableObjects: disableObjects, lowMemory: lowMemory, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); ClassicAssert.AreEqual("OK", context.clusterTestUtils.AddDelSlotsRange(0, new List<(int, int)>() { (0, 16383) }, true, context.logger)); @@ -442,13 +446,13 @@ public void ClusterSRAddReplicaAfterPrimaryCheckpoint([Values] bool performRMW, [Test, Order(8)] [Category("REPLICATION")] - public void ClusterSRPrimaryRestart([Values] bool performRMW, [Values] bool disableObjects) + public async Task ClusterSRPrimaryRestart([Values] bool performRMW, [Values] bool disableObjects) { var replica_count = 1;// Per primary var primary_count = 1; var nodes_count = primary_count + (primary_count * replica_count); ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, tryRecover: true, disableObjects: disableObjects, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, tryRecover: true, disableObjects: disableObjects, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); ClassicAssert.AreEqual("OK", context.clusterTestUtils.AddDelSlotsRange(0, new List<(int, int)>() { (0, 16383) }, true, context.logger)); @@ -481,7 +485,7 @@ public void ClusterSRPrimaryRestart([Values] bool performRMW, [Values] bool disa if (!disableObjects) objectStoreCurrentAofAddress = context.clusterTestUtils.GetObjectStoreCurrentAofAddress(0, context.logger); - context.nodes[0].Dispose(false); + await context.nodes[0].RunAsync(); Thread.Sleep(TimeSpan.FromSeconds(1)); // Restart Primary @@ -494,7 +498,7 @@ public void ClusterSRPrimaryRestart([Values] bool performRMW, [Values] bool disa useTLS: useTLS, cleanClusterConfig: false, asyncReplay: asyncReplay); - context.nodes[0].Start(); + await context.nodes[0].RunAsync(); context.CreateConnection(useTLS: useTLS); var storeRecoveredAofAddress = context.clusterTestUtils.GetStoreRecoveredAofAddress(0, context.logger); @@ -509,13 +513,13 @@ public void ClusterSRPrimaryRestart([Values] bool performRMW, [Values] bool disa [Test, Order(9)] [Category("REPLICATION")] - public void ClusterSRRedirectWrites() + public async Task ClusterSRRedirectWrites() { var replica_count = 1;// Per primary var primary_count = 1; var nodes_count = primary_count + (primary_count * replica_count); ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); var (shards, _) = context.clusterTestUtils.SimpleSetupCluster(primary_count, replica_count, logger: context.logger); @@ -537,10 +541,10 @@ public void ClusterSRRedirectWrites() [Test, Order(10)] [Category("REPLICATION")] - public void ClusterSRReplicaOfTest([Values] bool performRMW) + public async Task ClusterSRReplicaOfTest([Values] bool performRMW) { var nodes_count = 2; - context.CreateInstances(nodes_count, tryRecover: true, disableObjects: true, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, tryRecover: true, disableObjects: true, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); ClassicAssert.AreEqual("OK", context.clusterTestUtils.AddDelSlotsRange(0, [(0, 16383)], true, context.logger)); @@ -573,13 +577,13 @@ public void ClusterSRReplicaOfTest([Values] bool performRMW) [Test, Order(11)] [Category("REPLICATION")] - public void ClusterReplicationSimpleFailover([Values] bool performRMW, [Values] bool checkpoint) + public async Task ClusterReplicationSimpleFailover([Values] bool performRMW, [Values] bool checkpoint) { var replica_count = 1;// Per primary var primary_count = 1; var nodes_count = primary_count + (primary_count * replica_count); ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, disableObjects: true, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, disableObjects: true, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); var (shards, _) = context.clusterTestUtils.SimpleSetupCluster(primary_count, replica_count, logger: context.logger); @@ -643,13 +647,13 @@ public void ClusterReplicationSimpleFailover([Values] bool performRMW, [Values] [Test, Order(12)] [Category("REPLICATION")] - public void ClusterFailoverAttachReplicas([Values] bool performRMW, [Values] bool takePrimaryCheckpoint, [Values] bool takeNewPrimaryCheckpoint, [Values] bool enableIncrementalSnapshots) + public async Task ClusterFailoverAttachReplicas([Values] bool performRMW, [Values] bool takePrimaryCheckpoint, [Values] bool takeNewPrimaryCheckpoint, [Values] bool enableIncrementalSnapshots) { var replica_count = 2; // Per primary var primary_count = 1; var nodes_count = primary_count + (primary_count * replica_count); ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, disableObjects: true, EnableIncrementalSnapshots: enableIncrementalSnapshots, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, disableObjects: true, EnableIncrementalSnapshots: enableIncrementalSnapshots, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); var (shards, _) = context.clusterTestUtils.SimpleSetupCluster(primary_count, replica_count, logger: context.logger); @@ -693,6 +697,7 @@ public void ClusterFailoverAttachReplicas([Values] bool performRMW, [Values] boo context.ValidateKVCollectionAgainstReplica(ref context.kvPairs, 1); // Simulate primary crash + await context.nodes[0].StopAsync(); context.nodes[0].Dispose(); context.nodes[0] = null; @@ -724,13 +729,13 @@ public void ClusterFailoverAttachReplicas([Values] bool performRMW, [Values] boo [Test, Order(13)] [Category("REPLICATION")] - public void ClusterReplicationCheckpointCleanupTest([Values] bool performRMW, [Values] bool disableObjects, [Values] bool enableIncrementalSnapshots) + public async Task ClusterReplicationCheckpointCleanupTest([Values] bool performRMW, [Values] bool disableObjects, [Values] bool enableIncrementalSnapshots) { var replica_count = 1;//Per primary var primary_count = 1; var nodes_count = primary_count + (primary_count * replica_count); ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, tryRecover: true, disableObjects: disableObjects, lowMemory: true, SegmentSize: "4k", EnableIncrementalSnapshots: enableIncrementalSnapshots, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, tryRecover: true, disableObjects: disableObjects, lowMemory: true, SegmentSize: "4k", EnableIncrementalSnapshots: enableIncrementalSnapshots, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); ClassicAssert.AreEqual("OK", context.clusterTestUtils.AddDelSlotsRange(0, [(0, 16383)], true, context.logger)); context.clusterTestUtils.BumpEpoch(0, logger: context.logger); @@ -757,13 +762,13 @@ public void ClusterReplicationCheckpointCleanupTest([Values] bool performRMW, [V [Test, Order(14)] [Category("REPLICATION")] - public void ClusterMainMemoryReplicationAttachReplicas() + public async Task ClusterMainMemoryReplicationAttachReplicas() { var replica_count = 2; // Per primary var primary_count = 1; var nodes_count = primary_count + (primary_count * replica_count); ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, disableObjects: true, MainMemoryReplication: true, OnDemandCheckpoint: true, CommitFrequencyMs: -1, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, disableObjects: true, MainMemoryReplication: true, OnDemandCheckpoint: true, CommitFrequencyMs: -1, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); ClassicAssert.AreEqual("OK", context.clusterTestUtils.AddDelSlotsRange(0, new List<(int, int)>() { (0, 16383) }, true)); @@ -801,13 +806,13 @@ public void ClusterMainMemoryReplicationAttachReplicas() [Test, Order(15)] [Category("REPLICATION")] - public void ClusterDontKnowReplicaFailTest([Values] bool performRMW, [Values] bool MainMemoryReplication, [Values] bool onDemandCheckpoint, [Values] bool useReplicaOf) + public async Task ClusterDontKnowReplicaFailTest([Values] bool performRMW, [Values] bool MainMemoryReplication, [Values] bool onDemandCheckpoint, [Values] bool useReplicaOf) { var replica_count = 1;// Per primary var primary_count = 1; var nodes_count = primary_count + (primary_count * replica_count); ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, disableObjects: true, MainMemoryReplication: MainMemoryReplication, OnDemandCheckpoint: onDemandCheckpoint, CommitFrequencyMs: -1, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, disableObjects: true, MainMemoryReplication: MainMemoryReplication, OnDemandCheckpoint: onDemandCheckpoint, CommitFrequencyMs: -1, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); var primaryNodeIndex = 0; @@ -854,13 +859,13 @@ public void ClusterDontKnowReplicaFailTest([Values] bool performRMW, [Values] bo [Test, Order(16)] [Category("REPLICATION")] - public void ClusterDivergentReplicasTest([Values] bool performRMW, [Values] bool disableObjects, [Values] bool ckptBeforeDivergence) - => ClusterDivergentReplicasTest(performRMW, disableObjects, ckptBeforeDivergence, false, false, fastCommit: false); + public async Task ClusterDivergentReplicasTest([Values] bool performRMW, [Values] bool disableObjects, [Values] bool ckptBeforeDivergence) + => await ClusterDivergentReplicasTest(performRMW, disableObjects, ckptBeforeDivergence, false, false, fastCommit: false); [Test, Order(17)] [Category("REPLICATION")] - public void ClusterDivergentCheckpointTest([Values] bool performRMW, [Values] bool disableObjects) - => ClusterDivergentReplicasTest( + public async Task ClusterDivergentCheckpointTest([Values] bool performRMW, [Values] bool disableObjects) + => await ClusterDivergentReplicasTest( performRMW, disableObjects, ckptBeforeDivergence: true, @@ -870,8 +875,8 @@ public void ClusterDivergentCheckpointTest([Values] bool performRMW, [Values] bo [Test, Order(18)] [Category("REPLICATION")] - public void ClusterDivergentReplicasMMTest([Values] bool performRMW, [Values] bool disableObjects, [Values] bool ckptBeforeDivergence) - => ClusterDivergentReplicasTest( + public async Task ClusterDivergentReplicasMMTest([Values] bool performRMW, [Values] bool disableObjects, [Values] bool ckptBeforeDivergence) + => await ClusterDivergentReplicasTest( performRMW, disableObjects, ckptBeforeDivergence, @@ -881,8 +886,8 @@ public void ClusterDivergentReplicasMMTest([Values] bool performRMW, [Values] bo [Test, Order(19)] [Category("REPLICATION")] - public void ClusterDivergentCheckpointMMTest([Values] bool performRMW, [Values] bool disableObjects) - => ClusterDivergentReplicasTest( + public async Task ClusterDivergentCheckpointMMTest([Values] bool performRMW, [Values] bool disableObjects) + => await ClusterDivergentReplicasTest( performRMW, disableObjects, ckptBeforeDivergence: true, @@ -892,8 +897,8 @@ public void ClusterDivergentCheckpointMMTest([Values] bool performRMW, [Values] [Test, Order(20)] [Category("REPLICATION")] - public void ClusterDivergentCheckpointMMFastCommitTest([Values] bool disableObjects, [Values] bool mainMemoryReplication) - => ClusterDivergentReplicasTest( + public async Task ClusterDivergentCheckpointMMFastCommitTest([Values] bool disableObjects, [Values] bool mainMemoryReplication) + => await ClusterDivergentReplicasTest( performRMW: false, disableObjects: disableObjects, ckptBeforeDivergence: true, @@ -901,14 +906,14 @@ public void ClusterDivergentCheckpointMMFastCommitTest([Values] bool disableObje mainMemoryReplication: mainMemoryReplication, fastCommit: true); - void ClusterDivergentReplicasTest(bool performRMW, bool disableObjects, bool ckptBeforeDivergence, bool multiCheckpointAfterDivergence, bool mainMemoryReplication, bool fastCommit) + async Task ClusterDivergentReplicasTest(bool performRMW, bool disableObjects, bool ckptBeforeDivergence, bool multiCheckpointAfterDivergence, bool mainMemoryReplication, bool fastCommit) { var set = false; var replica_count = 2;// Per primary var primary_count = 1; var nodes_count = primary_count + (primary_count * replica_count); ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, disableObjects: disableObjects, MainMemoryReplication: mainMemoryReplication, CommitFrequencyMs: mainMemoryReplication ? -1 : 0, OnDemandCheckpoint: mainMemoryReplication, FastCommit: fastCommit, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, disableObjects: disableObjects, MainMemoryReplication: mainMemoryReplication, CommitFrequencyMs: mainMemoryReplication ? -1 : 0, OnDemandCheckpoint: mainMemoryReplication, FastCommit: fastCommit, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); _ = context.clusterTestUtils.SimpleSetupCluster(primary_count, replica_count, logger: context.logger); @@ -979,7 +984,8 @@ void ClusterDivergentReplicasTest(bool performRMW, bool disableObjects, bool ckp context.clusterTestUtils.WaitForReplicaAofSync(oldPrimaryIndex, replicaIndex, context.logger); // Dispose primary - context.nodes[oldPrimaryIndex].Dispose(false); + await context.nodes[oldPrimaryIndex].StopAsync(); + context.nodes[oldPrimaryIndex].Dispose(); ; context.nodes[oldPrimaryIndex] = null; // Re-assign slots to replica manually since failover option was not @@ -1029,7 +1035,7 @@ void ClusterDivergentReplicasTest(bool performRMW, bool disableObjects, bool ckp [Test, Order(21)] [Category("REPLICATION")] - public void ClusterReplicateFails() + public async Task ClusterReplicateFails() { const string UserName = "temp-user"; const string Password = "temp-password"; @@ -1042,7 +1048,7 @@ public void ClusterReplicateFails() ServerCredential userCreds = new(UserName, Password, IsAdmin: true, UsedForClusterAuth: false, IsClearText: true); context.GenerateCredentials([userCreds, clusterCreds]); - context.CreateInstances(2, disableObjects: true, disablePubSub: true, enableAOF: true, clusterCreds: clusterCreds, useAcl: true, MainMemoryReplication: true, CommitFrequencyMs: -1, asyncReplay: asyncReplay); + await context.CreateInstances(2, disableObjects: true, disablePubSub: true, enableAOF: true, clusterCreds: clusterCreds, useAcl: true, MainMemoryReplication: true, CommitFrequencyMs: -1, asyncReplay: asyncReplay); var primaryEndpoint = (IPEndPoint)context.endpoints.First(); var replicaEndpoint = (IPEndPoint)context.endpoints.Last(); @@ -1063,7 +1069,7 @@ public void ClusterReplicateFails() } [Test, Order(22)] - public void ClusterReplicationCheckpointAlignmentTest([Values] bool performRMW) + public async Task ClusterReplicationCheckpointAlignmentTest([Values] bool performRMW) { var replica_count = 1;// Per primary var primary_count = 1; @@ -1071,7 +1077,7 @@ public void ClusterReplicationCheckpointAlignmentTest([Values] bool performRMW) var primaryNodeIndex = 0; var replicaNodeIndex = 1; ClassicAssert.IsTrue(primary_count > 0); - context.CreateInstances(nodes_count, disableObjects: false, MainMemoryReplication: true, CommitFrequencyMs: -1, OnDemandCheckpoint: true, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); + await context.CreateInstances(nodes_count, disableObjects: false, MainMemoryReplication: true, CommitFrequencyMs: -1, OnDemandCheckpoint: true, enableAOF: true, useTLS: useTLS, asyncReplay: asyncReplay); context.CreateConnection(useTLS: useTLS); _ = context.clusterTestUtils.SimpleSetupCluster(primary_count, replica_count, logger: context.logger); @@ -1105,9 +1111,11 @@ public void ClusterReplicationCheckpointAlignmentTest([Values] bool performRMW) context.ValidateKVCollectionAgainstReplica(ref context.kvPairs, replicaNodeIndex); // Dispose primary and delete data - context.nodes[primaryNodeIndex].Dispose(true); + await context.nodes[primaryNodeIndex].StopAsync(); + context.nodes[primaryNodeIndex].Dispose(); // Dispose primary but do not delete data - context.nodes[replicaNodeIndex].Dispose(false); + await context.nodes[replicaNodeIndex].StopAsync(); + context.nodes[replicaNodeIndex].Dispose(); // Restart primary and do not recover context.nodes[primaryNodeIndex] = context.CreateInstance( @@ -1122,7 +1130,7 @@ public void ClusterReplicationCheckpointAlignmentTest([Values] bool performRMW) useTLS: useTLS, cleanClusterConfig: true, asyncReplay: asyncReplay); - context.nodes[primaryNodeIndex].Start(); + await context.nodes[primaryNodeIndex].RunAsync(); // Restart secondary and recover context.nodes[replicaNodeIndex] = context.CreateInstance( @@ -1137,7 +1145,7 @@ public void ClusterReplicationCheckpointAlignmentTest([Values] bool performRMW) useTLS: useTLS, cleanClusterConfig: true, asyncReplay: asyncReplay); - context.nodes[replicaNodeIndex].Start(); + await context.nodes[replicaNodeIndex].RunAsync(); context.CreateConnection(useTLS: useTLS); // Assert primary version is 1 and replica has recovered to previous checkpoint diff --git a/test/Garnet.test.cluster/ClusterTestContext.cs b/test/Garnet.test.cluster/ClusterTestContext.cs index 8bc92d8668..224ee7af4e 100644 --- a/test/Garnet.test.cluster/ClusterTestContext.cs +++ b/test/Garnet.test.cluster/ClusterTestContext.cs @@ -22,7 +22,7 @@ public class ClusterTestContext { public CredentialManager credManager; public string TestFolder; - public GarnetServer[] nodes = null; + public GarnetApplication[] nodes = null; public EndPointCollection endpoints; public TextWriter logTextWriter = TestContext.Progress; public ILoggerFactory loggerFactory; @@ -64,7 +64,7 @@ public void TearDown() waiter?.Dispose(); clusterTestUtils?.Dispose(); loggerFactory?.Dispose(); - if (!Task.Run(() => DisposeCluster()).Wait(TimeSpan.FromSeconds(15))) + if (!Task.Run(async () => await DisposeCluster()).Wait(TimeSpan.FromSeconds(15))) logger?.LogError("Timed out waiting for DisposeCluster"); if (!Task.Run(() => TestUtils.DeleteDirectory(TestFolder, true)).Wait(TimeSpan.FromSeconds(15))) logger?.LogError("Timed out waiting for DisposeCluster"); @@ -100,7 +100,7 @@ public void RegisterCustomTxn(string name, Func proc /// /// /// - public void CreateInstances( + public async Task CreateInstances( int shards, bool cleanClusterConfig = true, bool tryRecover = false, @@ -166,7 +166,7 @@ public void CreateInstances( luaMemoryLimit: luaMemoryLimit); foreach (var node in nodes) - node.Start(); + await node.RunAsync(); } /// @@ -195,7 +195,7 @@ public void CreateInstances( /// /// /// - public GarnetServer CreateInstance( + public GarnetApplication CreateInstance( int Port, bool cleanClusterConfig = true, bool disableEpochCollision = false, @@ -252,14 +252,18 @@ public GarnetServer CreateInstance( authPassword: clusterCreds.password, certificates: certificates); - return new GarnetServer(opts, loggerFactory); + var builder = GarnetApplication.CreateHostBuilder([], opts); + + var app = builder.Build(); + + return app; } /// /// Dispose created instances /// - public void DisposeCluster() + public async Task DisposeCluster() { if (nodes != null) { @@ -268,6 +272,7 @@ public void DisposeCluster() if (nodes[i] != null) { logger.LogDebug("\t a. Dispose node {testName}", TestContext.CurrentContext.Test.Name); + await nodes[i].StopAsync(); nodes[i].Dispose(); nodes[i] = null; logger.LogDebug("\t b. Dispose node {testName}", TestContext.CurrentContext.Test.Name); diff --git a/test/Garnet.test.cluster/RedirectTests/ClusterSlotVerificationTests.cs b/test/Garnet.test.cluster/RedirectTests/ClusterSlotVerificationTests.cs index 938d54cf44..00a826117a 100644 --- a/test/Garnet.test.cluster/RedirectTests/ClusterSlotVerificationTests.cs +++ b/test/Garnet.test.cluster/RedirectTests/ClusterSlotVerificationTests.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; using Garnet.common; using Garnet.server; using Microsoft.Extensions.Logging; @@ -195,12 +196,12 @@ private void ResetSlot() } [OneTimeSetUp] - public void OneTimeSetUp() + public async Task OneTimeSetUp() { context = new ClusterTestContext(); context.Setup([]); - context.CreateInstances(3, enableLua: true); + await context.CreateInstances(3, enableLua: true); context.RegisterCustomTxn( "CLUSTERGETPROC", diff --git a/test/Garnet.test/CacheSizeTrackerTests.cs b/test/Garnet.test/CacheSizeTrackerTests.cs index 41dfabddf5..91e14ff7e3 100644 --- a/test/Garnet.test/CacheSizeTrackerTests.cs +++ b/test/Garnet.test/CacheSizeTrackerTests.cs @@ -3,6 +3,7 @@ using System; using System.Threading; +using System.Threading.Tasks; using Garnet.server; using NUnit.Framework; using NUnit.Framework.Legacy; @@ -17,24 +18,28 @@ namespace Garnet.test [TestFixture] public class CacheSizeTrackerTests { - GarnetServer server; + GarnetApplication server; TsavoriteKV objStore; CacheSizeTracker cacheSizeTracker; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, MemorySize: "2k", PageSize: "512", lowMemory: true, objectStoreIndexSize: "1k", objectStoreHeapMemorySize: "5k"); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, MemorySize: "2k", PageSize: "512", lowMemory: true, objectStoreIndexSize: "1k", objectStoreHeapMemorySize: "5k"); + await server.RunAsync(); objStore = server.Provider.StoreWrapper.objectStore; cacheSizeTracker = server.Provider.StoreWrapper.objectStoreSizeTracker; } [TearDown] - public void TearDown() + public async Task TearDown() { - server?.Dispose(); + if (server != null) + { + await server.StopAsync(); + server.Dispose(); + } TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } @@ -90,11 +95,12 @@ public void IncreaseEmptyPageCountTest() } [Test] - public void ReadCacheIncreaseEmptyPageCountTest() + public async Task ReadCacheIncreaseEmptyPageCountTest() { - server?.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, MemorySize: "1k", PageSize: "512", lowMemory: true, objectStoreIndexSize: "1k", objectStoreReadCacheHeapMemorySize: "1k", enableObjectStoreReadCache: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, MemorySize: "1k", PageSize: "512", lowMemory: true, objectStoreIndexSize: "1k", objectStoreReadCacheHeapMemorySize: "1k", enableObjectStoreReadCache: true); + await server.RunAsync(); objStore = server.Provider.StoreWrapper.objectStore; cacheSizeTracker = server.Provider.StoreWrapper.objectStoreSizeTracker; diff --git a/test/Garnet.test/GarnetBitmapTests.cs b/test/Garnet.test/GarnetBitmapTests.cs index 627a4984d4..c4d812f342 100644 --- a/test/Garnet.test/GarnetBitmapTests.cs +++ b/test/Garnet.test/GarnetBitmapTests.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using Garnet.common; using Garnet.server; using NUnit.Framework; @@ -13,21 +14,22 @@ namespace Garnet.test { public class GarnetBitmapTests { - GarnetServer server; + GarnetApplication server; Random r; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + await server.RunAsync(); r = new Random(674386); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } @@ -438,15 +440,16 @@ public void BitmapBitCountNegativeOffsets() [Test, Order(10)] [Category("BITCOUNT")] - public void BitmapBitCountTest_LTM() + public async Task BitmapBitCountTest_LTM() { int bitmapBytes = 512; + await server.StopAsync(); server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: (bitmapBytes << 2).ToString(), PageSize: (bitmapBytes << 1).ToString()); - server.Start(); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -635,15 +638,16 @@ public void BitmapBitPosOffsetsTest() [Test, Order(14)] [Category("BITPOS")] - public void BitmapBitPosTest_LTM() + public async Task BitmapBitPosTest_LTM() { int bitmapBytes = 512; + await server.StopAsync(); server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: (bitmapBytes << 2).ToString(), PageSize: (bitmapBytes << 1).ToString()); - server.Start(); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -1280,17 +1284,18 @@ public unsafe void BitmapBitfieldGetTest_PCT([Values(RespCommand.BITFIELD, RespC [Test, Order(23)] [Category("BITFIELD")] - public void BitmapBitfieldGetTest_LTM([Values(RespCommand.BITFIELD, RespCommand.BITFIELD_RO)] RespCommand testCmd) + public async Task BitmapBitfieldGetTest_LTM([Values(RespCommand.BITFIELD, RespCommand.BITFIELD_RO)] RespCommand testCmd) { int bitmapBytes = 512; + await server.StopAsync(); server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: (bitmapBytes << 2).ToString(), PageSize: (bitmapBytes << 1).ToString()); //MemorySize: "16g", //PageSize: "32m"); - server.Start(); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -1481,17 +1486,18 @@ public void BitmapBitfieldSetTest() [Test, Order(26)] [Category("BITFIELD")] - public void BitmapBitfieldSetTest_LTM() + public async Task BitmapBitfieldSetTest_LTM() { int bitmapBytes = 512; + await server.StopAsync(); server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: (bitmapBytes << 2).ToString(), PageSize: (bitmapBytes << 1).ToString()); //MemorySize: "16g", //PageSize: "32m"); - server.Start(); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -1947,17 +1953,18 @@ public void BitmapBitfieldSignedIncrTest() [Test, Order(29)] [Category("BITFIELD")] - public void BitmapBitfieldIncrTest_LTM() + public async Task BitmapBitfieldIncrTest_LTM() { int bitmapBytes = 512; + await server.StopAsync(); server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: (bitmapBytes << 2).ToString(), PageSize: (bitmapBytes << 1).ToString()); //MemorySize: "16g", //PageSize: "32m"); - server.Start(); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); diff --git a/test/Garnet.test/GarnetClientTests.cs b/test/Garnet.test/GarnetClientTests.cs index 56498b2fcc..8d362472ff 100644 --- a/test/Garnet.test/GarnetClientTests.cs +++ b/test/Garnet.test/GarnetClientTests.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using Garnet.common; +using Microsoft.Extensions.Hosting; using NUnit.Framework; using NUnit.Framework.Legacy; @@ -117,10 +118,10 @@ static void WaitAndReset(ManualResetEventSlim e) } [Test] - public void SetGetWithCallback([Values] bool useTLS) + public async Task SetGetWithCallback([Values] bool useTLS) { - using var server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, EnableTLS: useTLS); - server.Start(); + var server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, EnableTLS: useTLS); + await server.RunAsync(); using var db = TestUtils.GetGarnetClient(useTLS); db.Connect(); @@ -142,13 +143,16 @@ public void SetGetWithCallback([Values] bool useTLS) e.Set(); }); e.Wait(); + + await server.StopAsync(); + server.Dispose(); } [Test] - public void SimpleMetricsTest([Values] bool recordLatency) + public async Task SimpleMetricsTest([Values] bool recordLatency) { - using var server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + var server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + await server.RunAsync(); var db = TestUtils.GetGarnetClient(recordLatency: recordLatency); db.Connect(); @@ -174,13 +178,16 @@ public void SimpleMetricsTest([Values] bool recordLatency) db.Dispose(); metrics = db.GetLatencyMetrics(); ClassicAssert.AreEqual(0, metrics.Length); // Should be 0 after dispose + + await server.StopAsync(); + server.Dispose(); } [Test] public async Task SimpleStringArrayTest([Values] bool stringParams) { - using var server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + var server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + await server.RunAsync(); var db = TestUtils.GetGarnetClient(); db.Connect(); @@ -190,13 +197,16 @@ public async Task SimpleStringArrayTest([Values] bool stringParams) int.Parse(await db.ExecuteForStringResultAsync(Encoding.ASCII.GetBytes("$6\r\nINCRBY\r\n"), [Encoding.ASCII.GetBytes("myKey"), Encoding.ASCII.GetBytes("10")])); ClassicAssert.AreEqual(10, n); + + await server.StopAsync(); + server.Dispose(); } [Test] public async Task SimpleNoArgsTest() { - using var server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + var server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + await server.RunAsync(); var db = TestUtils.GetGarnetClient(); db.Connect(); @@ -206,14 +216,17 @@ public async Task SimpleNoArgsTest() result = await db.ExecuteForStringResultAsync("ASKING"); ClassicAssert.AreEqual("OK", result); + + await server.StopAsync(); + server.Dispose(); } [Test] public async Task SimpleIncrTest([Values] bool stringParams) { ManualResetEventSlim e = new(); - using var server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + var server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + await server.RunAsync(); var key = "mykey"; var db = TestUtils.GetGarnetClient(); @@ -268,14 +281,17 @@ public async Task SimpleIncrTest([Values] bool stringParams) }); } WaitAndReset(e); + + await server.StopAsync(); + server.Dispose(); } [Test] public async Task SimpleDecrTest([Values] bool stringParams) { ManualResetEventSlim e = new(); - using var server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + var server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + await server.RunAsync(); var key = "mykey"; var db = TestUtils.GetGarnetClient(); @@ -330,13 +346,16 @@ public async Task SimpleDecrTest([Values] bool stringParams) }); } WaitAndReset(e); + + await server.StopAsync(); + server.Dispose(); } [Test] public async Task CanUseSetNxStringResultAsync() { - using var server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + var server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + await server.RunAsync(); var db = TestUtils.GetGarnetClient(); db.Connect(); @@ -349,13 +368,16 @@ public async Task CanUseSetNxStringResultAsync() var resultMykey = await db.StringGetAsync("mykey"); ClassicAssert.AreEqual("Hello", resultMykey); + + await server.StopAsync(); + server.Dispose(); } [Test] public async Task CanUseMGetTests([Values] bool disableObjectStore) { - using var server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: disableObjectStore); - server.Start(); + var server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: disableObjectStore); + await server.RunAsync(); var db = TestUtils.GetGarnetClient(); db.Connect(); @@ -416,6 +438,9 @@ public async Task CanUseMGetTests([Values] bool disableObjectStore) } tokenSource.Dispose(); + + await server.StopAsync(); + server.Dispose(); } private async Task ReadValuesMGet(string[] keys, CancellationToken t) @@ -461,8 +486,8 @@ private void SimpleStringArrayCallback(long context, string[] result, string err public async Task CanDoBulkDeleteTests([Values] bool useStringType) { //KeyDeleteAsync - using var server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + var server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + await server.RunAsync(); var db = TestUtils.GetGarnetClient(); db.Connect(); @@ -552,6 +577,9 @@ public async Task CanDoBulkDeleteTests([Values] bool useStringType) var result = await db.ExecuteForStringResultAsync("EXISTS", [key]); ClassicAssert.AreEqual("0", result); } + + await server.StopAsync(); + server.Dispose(); } private static async Task DeleteKeysWithCT(string[] keys, Memory[] keysMB, ManualResetEventSlim mreObj, CancellationToken t, bool useMemoryType = false) diff --git a/test/Garnet.test/GarnetJSON/JsonCommandsTest.cs b/test/Garnet.test/GarnetJSON/JsonCommandsTest.cs index 7ed66c9d36..9f5b4cfe7b 100644 --- a/test/Garnet.test/GarnetJSON/JsonCommandsTest.cs +++ b/test/Garnet.test/GarnetJSON/JsonCommandsTest.cs @@ -5,6 +5,7 @@ using System.IO; using System.Reflection; using System.Threading; +using System.Threading.Tasks; using Garnet.server; using GarnetJSON; using NUnit.Framework; @@ -16,21 +17,22 @@ namespace Garnet.test [TestFixture] class JsonCommandsTest { - GarnetServer server; + GarnetApplication server; string binPath; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); binPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true, extensionAllowUnsignedAssemblies: true, extensionBinPaths: [binPath]); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, extensionAllowUnsignedAssemblies: true, extensionBinPaths: [binPath]); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } @@ -84,7 +86,7 @@ public void JsonSetGetTests() } [Test] - public void SaveRecoverTest() + public async Task SaveRecoverTest() { string key = "key"; RegisterCustomCommand(); @@ -102,10 +104,11 @@ public void SaveRecoverTest() while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true); RegisterCustomCommand(); - server.Start(); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -116,12 +119,13 @@ public void SaveRecoverTest() } [Test] - public void AofUpsertRecoverTest() + public async Task AofUpsertRecoverTest() { - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, enableAOF: true); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true); RegisterCustomCommand(); - server.Start(); + await server.RunAsync(); var key = "aofkey"; using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) @@ -133,10 +137,11 @@ public void AofUpsertRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); RegisterCustomCommand(); - server.Start(); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { diff --git a/test/Garnet.test/HyperLogLogTests.cs b/test/Garnet.test/HyperLogLogTests.cs index 646cfd86d4..5a819d46ad 100644 --- a/test/Garnet.test/HyperLogLogTests.cs +++ b/test/Garnet.test/HyperLogLogTests.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading.Tasks; using Garnet.server; using NUnit.Framework; using NUnit.Framework.Legacy; @@ -12,23 +13,24 @@ namespace Garnet.test { - public unsafe class HyperLogLogTests + public class HyperLogLogTests { - GarnetServer server; + GarnetApplication server; Random r; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + await server.RunAsync(); r = new Random(674386); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } @@ -329,7 +331,7 @@ private static unsafe ulong MurmurHash2x64A(byte* bString, int len, uint seed = [Test] [Repeat(1)] - public void HyperLogLogUpdateReturnTest() + public unsafe void HyperLogLogUpdateReturnTest() { using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -387,7 +389,7 @@ private void RandomString(ref byte[] valuebuffer) [Test] [Repeat(1)] - public void HyperLogLogMultiValueUpdateReturnTest() + public unsafe void HyperLogLogMultiValueUpdateReturnTest() { using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -573,21 +575,22 @@ public void HyperLogLogTestPFADDV2() [TestCase(32)] [TestCase(4096)] [Repeat(1)] - public void HyperLogLogPFADD_LTM(int seqSize) + public async Task HyperLogLogPFADD_LTM(int seqSize) { bool sparse = seqSize < 128 ? true : false; + await server.StopAsync(); server.Dispose(); if (seqSize < 128) - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: "1024", PageSize: "512"); else - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: "32k", PageSize: "16k"); - server.Start(); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -693,14 +696,15 @@ public void HyperLogLogTestPFMERGE_SparseToSparseV2() [Test] [Repeat(10)] - public void HyperLogLogTestPFMERGE_LTM_SparseToSparse() + public async Task HyperLogLogTestPFMERGE_LTM_SparseToSparse() { + await server.StopAsync(); server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: "1024", PageSize: "512"); - server.Start(); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -803,13 +807,14 @@ public void HyperLogLogTestPFMERGE_SparseToDenseV2() [TestCase(false)] [TestCase(true)] [Repeat(1)] - public void HyperLogLogTestPFMERGE_LTM_SparseToDense(bool reverse) + public async Task HyperLogLogTestPFMERGE_LTM_SparseToDense(bool reverse) { + await server.StopAsync(); server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, MemorySize: "32k", PageSize: "16k"); - server.Start(); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -912,14 +917,15 @@ public void HyperLogLogTestPFMERGE_DenseToDenseV2() [Test] [Repeat(1)] - public void HyperLogLogTestPFMERGE_LTM_DenseToDense() + public async Task HyperLogLogTestPFMERGE_LTM_DenseToDense() { + await server.StopAsync(); server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: "32k", PageSize: "16k"); - server.Start(); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); diff --git a/test/Garnet.test/IndexGrowthTests.cs b/test/Garnet.test/IndexGrowthTests.cs index c08d2f90cb..9282c66385 100644 --- a/test/Garnet.test/IndexGrowthTests.cs +++ b/test/Garnet.test/IndexGrowthTests.cs @@ -3,6 +3,7 @@ using System; using System.Threading; +using System.Threading.Tasks; using NUnit.Framework; using NUnit.Framework.Legacy; using StackExchange.Redis; @@ -12,7 +13,7 @@ namespace Garnet.test [TestFixture] public class IndexGrowthTests { - GarnetServer server; + GarnetApplication server; private int indexResizeTaskDelaySeconds = 10; private int indexResizeWaitCycles = 2; @@ -23,17 +24,22 @@ public void Setup() } [TearDown] - public void TearDown() + public async Task TearDown() { - server?.Dispose(); + if (server != null) + { + await server.StopAsync(); + server.Dispose(); + } + TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } [Test] - public void IndexGrowthTest() + public async Task IndexGrowthTest() { - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true, indexSize: "64", indexMaxSize: "128", indexResizeFrequencySecs: indexResizeTaskDelaySeconds); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, indexSize: "64", indexMaxSize: "128", indexResizeFrequencySecs: indexResizeTaskDelaySeconds); + await server.RunAsync(); var store = server.Provider.StoreWrapper.store; @@ -68,10 +74,10 @@ public void IndexGrowthTest() } [Test] - public void ObjectStoreIndexGrowthTest() + public async Task ObjectStoreIndexGrowthTest() { - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true, objectStoreIndexSize: "64", objectStoreIndexMaxSize: "128", indexResizeFrequencySecs: indexResizeTaskDelaySeconds); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, objectStoreIndexSize: "64", objectStoreIndexMaxSize: "128", indexResizeFrequencySecs: indexResizeTaskDelaySeconds); + await server.RunAsync(); var objectStore = server.Provider.StoreWrapper.objectStore; @@ -115,10 +121,10 @@ private static void VerifyObjectStoreSetMembers(IDatabase db, RedisKey[] keys, R } [Test] - public void IndexGrowthTestWithDiskReadAndCheckpoint() + public async Task IndexGrowthTestWithDiskReadAndCheckpoint() { - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true, indexSize: "512", indexMaxSize: "1k", indexResizeFrequencySecs: indexResizeTaskDelaySeconds); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, indexSize: "512", indexMaxSize: "1k", indexResizeFrequencySecs: indexResizeTaskDelaySeconds); + await server.RunAsync(); var store = server.Provider.StoreWrapper.store; @@ -166,9 +172,10 @@ public void IndexGrowthTestWithDiskReadAndCheckpoint() while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, lowMemory: true, indexSize: "512", indexMaxSize: "1k"); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, lowMemory: true, indexSize: "512", indexMaxSize: "1k"); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -179,10 +186,10 @@ public void IndexGrowthTestWithDiskReadAndCheckpoint() } [Test] - public void ObjectStoreIndexGrowthTestWithDiskReadAndCheckpoint() + public async Task ObjectStoreIndexGrowthTestWithDiskReadAndCheckpoint() { - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true, objectStoreIndexSize: "512", objectStoreIndexMaxSize: "1k", indexResizeFrequencySecs: indexResizeTaskDelaySeconds); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, objectStoreIndexSize: "512", objectStoreIndexMaxSize: "1k", indexResizeFrequencySecs: indexResizeTaskDelaySeconds); + await server.RunAsync(); var objectStore = server.Provider.StoreWrapper.objectStore; @@ -230,9 +237,10 @@ public void ObjectStoreIndexGrowthTestWithDiskReadAndCheckpoint() while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, lowMemory: true, objectStoreIndexSize: "512", objectStoreIndexMaxSize: "1k"); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, lowMemory: true, objectStoreIndexSize: "512", objectStoreIndexMaxSize: "1k"); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { diff --git a/test/Garnet.test/LuaScriptTests.cs b/test/Garnet.test/LuaScriptTests.cs index 4ed1be723b..10ac592092 100644 --- a/test/Garnet.test/LuaScriptTests.cs +++ b/test/Garnet.test/LuaScriptTests.cs @@ -24,7 +24,7 @@ public class LuaScriptTests private readonly LuaMemoryManagementMode allocMode; private readonly string limitBytes; - protected GarnetServer server; + protected GarnetApplication server; public LuaScriptTests(LuaMemoryManagementMode allocMode, string limitBytes) { @@ -33,16 +33,17 @@ public LuaScriptTests(LuaMemoryManagementMode allocMode, string limitBytes) } [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, enableLua: true, luaMemoryMode: allocMode, luaMemoryLimit: limitBytes); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableLua: true, luaMemoryMode: allocMode, luaMemoryLimit: limitBytes); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/ObjectTestsForOutput.cs b/test/Garnet.test/ObjectTestsForOutput.cs index bcaf7b256a..080d2e0bb5 100644 --- a/test/Garnet.test/ObjectTestsForOutput.cs +++ b/test/Garnet.test/ObjectTestsForOutput.cs @@ -11,20 +11,21 @@ namespace Garnet.test [TestFixture] public class ObjectTestsForOutput { - protected GarnetServer server; + protected GarnetApplication server; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: false); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: false); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/ReadCacheTests.cs b/test/Garnet.test/ReadCacheTests.cs index 80aa968484..2aa6a3cbb0 100644 --- a/test/Garnet.test/ReadCacheTests.cs +++ b/test/Garnet.test/ReadCacheTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. +using System.Threading.Tasks; using NUnit.Framework; using NUnit.Framework.Legacy; using StackExchange.Redis; @@ -10,19 +11,20 @@ namespace Garnet.test [TestFixture] public class ReadCacheTests { - GarnetServer server; + GarnetApplication server; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, enableReadCache: true, enableObjectStoreReadCache: true, lowMemory: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableReadCache: true, enableObjectStoreReadCache: true, lowMemory: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/Resp/ACL/AclConfigurationFileTests.cs b/test/Garnet.test/Resp/ACL/AclConfigurationFileTests.cs index bac1958332..c36c6d116f 100644 --- a/test/Garnet.test/Resp/ACL/AclConfigurationFileTests.cs +++ b/test/Garnet.test/Resp/ACL/AclConfigurationFileTests.cs @@ -29,8 +29,8 @@ public async Task EmptyInput() File.CreateText(configurationFile).Close(); // Ensure Garnet starts up with default user only - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -51,8 +51,8 @@ public async Task NoDefaultRule() File.WriteAllText(configurationFile, "user testA on >password123 +@admin\r\nuser testB on >passw0rd >password +@admin "); // Start up Garnet - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -77,8 +77,8 @@ public async Task WithDefaultRule() File.WriteAllText(configurationFile, "user testA on >password123 +@admin +@slow\r\nuser testB on >passw0rd >password +@admin\r\nuser default on nopass +@admin +@slow"); // Start up Garnet with a defined default user password - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile, defaultPassword: DummyPassword); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile, defaultPassword: DummyPassword); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -117,8 +117,8 @@ public async Task AclLoad() File.WriteAllText(configurationFile, originalConfigurationFile); // Start up Garnet - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile, defaultPassword: DummyPassword); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile, defaultPassword: DummyPassword); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -188,8 +188,8 @@ public async Task AclLoadErrors() File.WriteAllText(configurationFile, originalConfigurationFile); // Start up Garnet - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -243,8 +243,8 @@ public async Task DuplicateUserNames() var configurationFile = Path.Join(TestUtils.MethodTestDir, "users.acl"); File.WriteAllText(configurationFile, $"user test on >{DummyPassword} +@admin\r\nuser test off"); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -279,8 +279,10 @@ public void BadInputNonexistingFile() // NOTE: Do not create the configuration file var configurationFile = Path.Join(TestUtils.MethodTestDir, "users.acl"); + // TODO propagate the ACLException to builder + // Garnet should ignore the non-existing configuration file and start up with default user - Assert.Throws(() => TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile)); + Assert.Throws(() => TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile).Register?.GetType()); } /// @@ -294,8 +296,10 @@ public void BadInputMalformedStatement() var configurationFile = Path.Join(TestUtils.MethodTestDir, "users.acl"); File.WriteAllText(configurationFile, "user test on >password123 +@admin\r\nuser testB badinput on >passw0rd >password +@admin "); + // TODO propagate the ACLException to builder + // Ensure Garnet starts up and just ignores the malformed statement - Assert.Throws(() => TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile)); + Assert.Throws(() => TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile).Register?.GetType()); } // Test numeric RespCommand rejected @@ -313,7 +317,7 @@ public void BadInputMalformedStatement() File.WriteAllText(configurationFile, "user test on >password123 +none"); // Ensure Garnet starts up and just ignores the malformed statement - Assert.Throws(() => TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile)); + Assert.Throws(() => TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile).Register?.GetType()); } @@ -323,12 +327,12 @@ public void BadInputMalformedStatement() File.WriteAllText(configurationFile, "user test on >password123 +invalid"); // Ensure Garnet starts up and just ignores the malformed statement - Assert.Throws(() => TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile)); + Assert.Throws(() => TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile).Register?.GetType()); } } [Test] - public void AclSave() + public async Task AclSave() { // Create a modified ACL that (1) removes two users, (2) adds one user, (3) removes one password and (4) removes the default user var originalConfigurationFile = @@ -342,8 +346,8 @@ public void AclSave() File.WriteAllText(configurationFile, originalConfigurationFile); // Start up Garnet - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile, defaultPassword: DummyPassword); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, aclFile: configurationFile, defaultPassword: DummyPassword); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); diff --git a/test/Garnet.test/Resp/ACL/AclTest.cs b/test/Garnet.test/Resp/ACL/AclTest.cs index 9f5e614cda..034a19a4e6 100644 --- a/test/Garnet.test/Resp/ACL/AclTest.cs +++ b/test/Garnet.test/Resp/ACL/AclTest.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using System.IO; +using System.Threading.Tasks; using NUnit.Framework; namespace Garnet.test.Resp.ACL @@ -44,7 +45,7 @@ abstract class AclTest /// /// Garnet server instance to use in the tests. /// - protected GarnetServer server = null; + protected GarnetApplication server = null; /// /// Creates working directory @@ -60,10 +61,11 @@ public virtual void BaseSetup() /// Cleans up any running working instances /// [TearDown] - public virtual void BaseTearDown() + public virtual async Task BaseTearDown() { if (server != null) { + await server.StopAsync(); server.Dispose(); server = null; } diff --git a/test/Garnet.test/Resp/ACL/BasicTests.cs b/test/Garnet.test/Resp/ACL/BasicTests.cs index bdbaa63651..1845a7e266 100644 --- a/test/Garnet.test/Resp/ACL/BasicTests.cs +++ b/test/Garnet.test/Resp/ACL/BasicTests.cs @@ -19,10 +19,10 @@ internal class BasicTests : AclTest /// Creates and starts the Garnet test server /// [SetUp] - public virtual void Setup() + public virtual async Task Setup() { - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); } /// diff --git a/test/Garnet.test/Resp/ACL/DeleteUserTests.cs b/test/Garnet.test/Resp/ACL/DeleteUserTests.cs index 69b142d32c..13dbe95212 100644 --- a/test/Garnet.test/Resp/ACL/DeleteUserTests.cs +++ b/test/Garnet.test/Resp/ACL/DeleteUserTests.cs @@ -18,10 +18,10 @@ class DeleteUserTests : AclTest /// Creates and starts the Garnet test server /// [SetUp] - public virtual void Setup() + public virtual async Task Setup() { - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); } /// diff --git a/test/Garnet.test/Resp/ACL/ParallelTests.cs b/test/Garnet.test/Resp/ACL/ParallelTests.cs index 129ff99027..0eb524e2fe 100644 --- a/test/Garnet.test/Resp/ACL/ParallelTests.cs +++ b/test/Garnet.test/Resp/ACL/ParallelTests.cs @@ -18,10 +18,10 @@ internal class ParallelTests : AclTest /// Creates and starts the Garnet test server /// [SetUp] - public virtual void Setup() + public virtual async Task Setup() { - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); } /// diff --git a/test/Garnet.test/Resp/ACL/RespCommandTests.cs b/test/Garnet.test/Resp/ACL/RespCommandTests.cs index b33d49c322..6dd3582811 100644 --- a/test/Garnet.test/Resp/ACL/RespCommandTests.cs +++ b/test/Garnet.test/Resp/ACL/RespCommandTests.cs @@ -24,14 +24,14 @@ public class RespCommandTests private IReadOnlyDictionary respCustomCommandsInfo; - private GarnetServer server; + private GarnetApplication server; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, defaultPassword: DefaultPassword, useAcl: true, enableLua: true); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, defaultPassword: DefaultPassword, useAcl: true, enableLua: true); // Register custom commands so we can test ACL'ing them ClassicAssert.IsTrue(TestUtils.TryGetCustomCommandsInfo(out respCustomCommandsInfo)); @@ -42,12 +42,13 @@ public void Setup() server.Register.NewTransactionProc("READWRITETX", () => new ReadWriteTxn(), new RespCommandsInfo { Arity = 4 }); server.Register.NewProcedure("SUM", () => new Sum()); - server.Start(); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/Resp/ACL/SetUserTests.cs b/test/Garnet.test/Resp/ACL/SetUserTests.cs index 669e233531..5434b3c80c 100644 --- a/test/Garnet.test/Resp/ACL/SetUserTests.cs +++ b/test/Garnet.test/Resp/ACL/SetUserTests.cs @@ -20,11 +20,11 @@ class SetUserTests : AclTest /// Tests that new connections start with default user when no users are defined /// [Test] - public void PasswordlessDefaultUserTest() + public async Task PasswordlessDefaultUserTest() { // Create a new test server without password - should automatically login default user - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); // Check user is authenticated as default using var lightClientRequest = TestUtils.CreateRequest(); @@ -43,8 +43,8 @@ public void PasswordlessDefaultUserTest() public async Task ProtectedDefaultUserErrorHandlingTest() { // Create a new test server with password - should disallow any operation - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, defaultPassword: DummyPassword); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, defaultPassword: DummyPassword); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -68,8 +68,8 @@ public async Task ProtectedDefaultUserErrorHandlingTest() public async Task ProtectedDefaultUserLoginImplicitTest() { // Create a new test server with password - should disallow any operation - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, defaultPassword: DummyPassword); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, defaultPassword: DummyPassword); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -90,8 +90,8 @@ public async Task ProtectedDefaultUserLoginImplicitTest() public async Task ProtectedDefaultUserLoginExplicitTest() { // Create a new test server with password - should disallow any operation - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true, defaultPassword: DummyPassword); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true, defaultPassword: DummyPassword); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -113,8 +113,8 @@ public async Task ProtectedDefaultUserLoginExplicitTest() public async Task EnableAndDisableUsers() { // Create a new test server without default password - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -168,8 +168,8 @@ public async Task EnableAndDisableUsers() public async Task AddPasswordFromCleartextTest() { // Create a new test server with password - should disallow any operation - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -198,8 +198,8 @@ public async Task AddPasswordFromCleartextTest() public async Task AddPasswordFromHashTest() { // Create a new test server with password - should disallow any operation - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -228,8 +228,8 @@ public async Task AddPasswordFromHashTest() public async Task RemovePasswordFromCleartextTest() { // Create a new test server with password - should disallow any operation - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -260,8 +260,8 @@ public async Task RemovePasswordFromCleartextTest() public async Task RemovePasswordFromHashTest() { // Create a new test server with password - should disallow any operation - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -292,8 +292,8 @@ public async Task RemovePasswordFromHashTest() public async Task AddDuplicatePasswordTest() { // Create a new test server with password - should disallow any operation - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -325,8 +325,8 @@ public async Task AddDuplicatePasswordTest() public async Task PasswordlessUserTest() { // Create a new test server with password - should disallow any operation - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -348,8 +348,8 @@ public async Task PasswordlessUserTest() public async Task ResetPasswordsTest() { // Create a new test server with password - should disallow any operation - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -392,8 +392,8 @@ public async Task AddAndRemoveCategoryTest() const string TestCategory = "admin"; // Create a new test server with password - should disallow any operation - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -448,8 +448,8 @@ public async Task AddAndRemoveCategoryTest() public async Task ResetUser() { // Create a new test server - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -493,8 +493,8 @@ public async Task ResetUser() public async Task BadInputEmpty() { // Create a new test server - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -518,8 +518,8 @@ public async Task BadInputEmpty() public async Task BadInputUnknownOperation() { // Create a new test server - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -543,8 +543,8 @@ public async Task BadInputUnknownOperation() public async Task KeyPatternsWildcard() { // Create a new test server - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, useAcl: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, useAcl: true); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); diff --git a/test/Garnet.test/Resp/GarnetAuthenticatorTests.cs b/test/Garnet.test/Resp/GarnetAuthenticatorTests.cs index af92c5dd47..889033f9c6 100644 --- a/test/Garnet.test/Resp/GarnetAuthenticatorTests.cs +++ b/test/Garnet.test/Resp/GarnetAuthenticatorTests.cs @@ -77,8 +77,8 @@ public async Task InvalidatingAuthorizationAsync() return true; }; - using GarnetServer server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, authenticationSettings: authSettings); - server.Start(); + var server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, authenticationSettings: authSettings); + await server.RunAsync(); using var c = TestUtils.GetGarnetClientSession(); c.Connect(); @@ -108,6 +108,9 @@ public async Task InvalidatingAuthorizationAsync() await c.ExecuteAsync("AUTH", "foo", "bar"); ClassicAssert.AreEqual(3, authCalls); + + await server.StopAsync(); + server.Dispose(); } } } \ No newline at end of file diff --git a/test/Garnet.test/RespAdminCommandsTests.cs b/test/Garnet.test/RespAdminCommandsTests.cs index 7bf4f07f06..ef05d8bbf5 100644 --- a/test/Garnet.test/RespAdminCommandsTests.cs +++ b/test/Garnet.test/RespAdminCommandsTests.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using Garnet.server; +using Microsoft.Extensions.Hosting; using NUnit.Framework; using NUnit.Framework.Legacy; using StackExchange.Redis; @@ -17,19 +18,20 @@ namespace Garnet.test [TestFixture] public class RespAdminCommandsTests { - GarnetServer server; + GarnetApplication server; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } @@ -157,13 +159,14 @@ public void SeSaveTest() } [Test] - public void SeSaveRecoverTest([Values] bool disableObj, [Values] bool useAzure) + public async Task SeSaveRecoverTest([Values] bool disableObj, [Values] bool useAzure) { if (useAzure) TestUtils.IgnoreIfNotRunningAzureTests(); + await server.StopAsync(); server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: disableObj, UseAzureStorage: useAzure); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: disableObj, UseAzureStorage: useAzure); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -176,9 +179,10 @@ public void SeSaveRecoverTest([Values] bool disableObj, [Values] bool useAzure) while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, UseAzureStorage: useAzure); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, UseAzureStorage: useAzure); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -189,7 +193,7 @@ public void SeSaveRecoverTest([Values] bool disableObj, [Values] bool useAzure) } [Test] - public void SeSaveRecoverObjectTest() + public async Task SeSaveRecoverObjectTest() { var key = "SeSaveRecoverTestObjectKey"; var ldata = new RedisValue[] { "a", "b", "c", "d" }; @@ -208,9 +212,10 @@ public void SeSaveRecoverObjectTest() while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -223,7 +228,7 @@ public void SeSaveRecoverObjectTest() } [Test] - public void SeSaveRecoverCustomObjectTest() + public async Task SeSaveRecoverCustomObjectTest() { string key = "key"; string field = "field1"; @@ -247,11 +252,12 @@ public void SeSaveRecoverCustomObjectTest() while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true); server.Register.NewCommand("MYDICTSET", CommandType.ReadModifyWrite, factory, new MyDictSet(), new RespCommandsInfo { Arity = 4 }); server.Register.NewCommand("MYDICTGET", CommandType.Read, factory, new MyDictGet(), new RespCommandsInfo { Arity = 3 }); - server.Start(); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -262,7 +268,7 @@ public void SeSaveRecoverCustomObjectTest() } [Test] - public void SeSaveRecoverCustomScriptTest() + public async Task SeSaveRecoverCustomScriptTest() { static void ValidateServerData(IDatabase db, string strKey, string strValue, string listKey, string listValue) { @@ -293,10 +299,11 @@ static void ValidateServerData(IDatabase db, string strKey, string strValue, str while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true); server.Register.NewProcedure("SETMAINANDOBJECT", () => new SetStringAndList()); - server.Start(); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -309,13 +316,14 @@ static void ValidateServerData(IDatabase db, string strKey, string strValue, str [TestCase(63, 2, 1)] [TestCase(16, 16, 1)] [TestCase(5, 64, 1)] - public void SeSaveRecoverMultipleObjectsTest(int memorySize, int recoveryMemorySize, int pageSize) + public async Task SeSaveRecoverMultipleObjectsTest(int memorySize, int recoveryMemorySize, int pageSize) { string sizeToString(int size) => size + "k"; + await server.StopAsync(); server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true, MemorySize: sizeToString(memorySize), PageSize: sizeToString(pageSize)); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, MemorySize: sizeToString(memorySize), PageSize: sizeToString(pageSize)); + await server.RunAsync(); var ldata = new RedisValue[] { "a", "b", "c", "d" }; var ldataArr = ldata.Select(x => x).Reverse().ToArray(); @@ -334,9 +342,10 @@ public void SeSaveRecoverMultipleObjectsTest(int memorySize, int recoveryMemoryS while (server.LastSave().Ticks == DateTimeOffset.FromUnixTimeSeconds(0).Ticks) Thread.Sleep(10); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, lowMemory: true, MemorySize: sizeToString(recoveryMemorySize), PageSize: sizeToString(pageSize), objectStoreHeapMemorySize: "64k"); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, lowMemory: true, MemorySize: sizeToString(recoveryMemorySize), PageSize: sizeToString(pageSize), objectStoreHeapMemorySize: "64k"); + await server.RunAsync(); ClassicAssert.LessOrEqual(server.Provider.StoreWrapper.objectStore.MaxAllocatedPageCount, (recoveryMemorySize / pageSize) + 1); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) @@ -358,13 +367,14 @@ public void SeSaveRecoverMultipleObjectsTest(int memorySize, int recoveryMemoryS [TestCase("16k", "16k")] [TestCase("5k", "8k")] [TestCase("5k", "64k")] - public void SeSaveRecoverMultipleKeysTest(string memorySize, string recoveryMemorySize) + public async Task SeSaveRecoverMultipleKeysTest(string memorySize, string recoveryMemorySize) { bool disableObj = true; + await server.StopAsync(); server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: disableObj, lowMemory: true, MemorySize: memorySize, PageSize: "512", enableAOF: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: disableObj, lowMemory: true, MemorySize: memorySize, PageSize: "512", enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -401,9 +411,10 @@ public void SeSaveRecoverMultipleKeysTest(string memorySize, string recoveryMemo db.Execute("COMMITAOF"); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: disableObj, tryRecover: true, lowMemory: true, MemorySize: recoveryMemorySize, PageSize: "512", enableAOF: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: disableObj, tryRecover: true, lowMemory: true, MemorySize: recoveryMemorySize, PageSize: "512", enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -417,11 +428,12 @@ public void SeSaveRecoverMultipleKeysTest(string memorySize, string recoveryMemo } [Test] - public void SeAofRecoverTest() + public async Task SeAofRecoverTest() { - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, enableAOF: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -431,9 +443,10 @@ public void SeAofRecoverTest() db.Execute("COMMITAOF"); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, enableAOF: true, tryRecover: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true, tryRecover: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { diff --git a/test/Garnet.test/RespAofAzureTests.cs b/test/Garnet.test/RespAofAzureTests.cs index 9787ba1e74..ff7a17b689 100644 --- a/test/Garnet.test/RespAofAzureTests.cs +++ b/test/Garnet.test/RespAofAzureTests.cs @@ -3,6 +3,7 @@ using System; using System.Threading; +using System.Threading.Tasks; using NUnit.Framework; using NUnit.Framework.Legacy; using StackExchange.Redis; @@ -12,7 +13,7 @@ namespace Garnet.test [TestFixture] public class RespAofAzureTests { - GarnetServer server; + GarnetApplication server; static readonly SortedSetEntry[] entries = [ new SortedSetEntry("a", 1), @@ -28,20 +29,24 @@ public class RespAofAzureTests ]; [SetUp] - public void Setup() + public async Task Setup() { - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, enableAOF: true, lowMemory: true, UseAzureStorage: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true, lowMemory: true, UseAzureStorage: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { - server?.Dispose(); + if (server != null) + { + await server.StopAsync(); + server.Dispose(); + } } [Test] - public void AofUpsertStoreRecoverTest() + public async Task AofUpsertStoreRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -51,9 +56,10 @@ public void AofUpsertStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -66,7 +72,7 @@ public void AofUpsertStoreRecoverTest() } [Test] - public void AofUpsertStoreAutoCommitRecoverTest() + public async Task AofUpsertStoreAutoCommitRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -76,9 +82,10 @@ public void AofUpsertStoreAutoCommitRecoverTest() } server.Store.WaitForCommit(); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -91,11 +98,12 @@ public void AofUpsertStoreAutoCommitRecoverTest() } [Test] - public void AofUpsertStoreAutoCommitCommitWaitRecoverTest() + public async Task AofUpsertStoreAutoCommitCommitWaitRecoverTest() { - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitWait: true, UseAzureStorage: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitWait: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -103,9 +111,10 @@ public void AofUpsertStoreAutoCommitCommitWaitRecoverTest() db.StringSet("SeAofUpsertRecoverTestKey1", "SeAofUpsertRecoverTestValue1"); db.StringSet("SeAofUpsertRecoverTestKey2", "SeAofUpsertRecoverTestValue2"); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -118,7 +127,7 @@ public void AofUpsertStoreAutoCommitCommitWaitRecoverTest() } [Test] - public void AofUpsertStoreCkptRecoverTest() + public async Task AofUpsertStoreCkptRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -136,9 +145,10 @@ public void AofUpsertStoreCkptRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -153,7 +163,7 @@ public void AofUpsertStoreCkptRecoverTest() } [Test] - public void AofRMWStoreRecoverTest() + public async Task AofRMWStoreRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -163,9 +173,10 @@ public void AofRMWStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -178,7 +189,7 @@ public void AofRMWStoreRecoverTest() } [Test] - public void AofDeleteStoreRecoverTest() + public async Task AofDeleteStoreRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -198,9 +209,10 @@ public void AofDeleteStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -215,7 +227,7 @@ public void AofDeleteStoreRecoverTest() } [Test] - public void AofExpiryRMWStoreRecoverTest() + public async Task AofExpiryRMWStoreRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -233,9 +245,10 @@ public void AofExpiryRMWStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -248,7 +261,7 @@ public void AofExpiryRMWStoreRecoverTest() } [Test] - public void AofRMWObjectStoreRecoverTest() + public async Task AofRMWObjectStoreRecoverTest() { var key = "AofRMWObjectStoreRecoverTestKey"; @@ -267,9 +280,10 @@ public void AofRMWObjectStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -285,7 +299,7 @@ public void AofRMWObjectStoreRecoverTest() } [Test] - public void AofDeleteObjectStoreRecoverTest() + public async Task AofDeleteObjectStoreRecoverTest() { var key1 = "AofDeleteObjectStoreRecoverTestKey1"; var key2 = "AofDeleteObjectStoreRecoverTestKey2"; @@ -313,9 +327,10 @@ public void AofDeleteObjectStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -328,7 +343,7 @@ public void AofDeleteObjectStoreRecoverTest() } [Test] - public void AofRMWObjectStoreCopyUpdateRecoverTest() + public async Task AofRMWObjectStoreCopyUpdateRecoverTest() { var key = "AofRMWObjectStoreRecoverTestKey"; @@ -349,9 +364,10 @@ public void AofRMWObjectStoreCopyUpdateRecoverTest() db.SortedSetAdd("AofRMWObjectStoreRecoverTestKey" + 1, newEntries); } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -367,7 +383,7 @@ public void AofRMWObjectStoreCopyUpdateRecoverTest() } [Test] - public void AofMultiRMWStoreCkptRecoverTest() + public async Task AofMultiRMWStoreCkptRecoverTest() { long ret = 0; using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) @@ -404,9 +420,10 @@ public void AofMultiRMWStoreCkptRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true, UseAzureStorage: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { diff --git a/test/Garnet.test/RespAofTests.cs b/test/Garnet.test/RespAofTests.cs index 90e8bb61e4..81004bac31 100644 --- a/test/Garnet.test/RespAofTests.cs +++ b/test/Garnet.test/RespAofTests.cs @@ -5,7 +5,9 @@ using System.Collections.Generic; using System.Linq; using System.Threading; +using System.Threading.Tasks; using Garnet.server; +using Microsoft.Extensions.Hosting; using NUnit.Framework; using NUnit.Framework.Legacy; using StackExchange.Redis; @@ -15,7 +17,7 @@ namespace Garnet.test [TestFixture] public class RespAofTests { - GarnetServer server; + GarnetApplication server; private IReadOnlyDictionary respCustomCommandsInfo; static readonly SortedSetEntry[] entries = @@ -33,24 +35,25 @@ public class RespAofTests ]; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); ClassicAssert.IsTrue(TestUtils.TryGetCustomCommandsInfo(out respCustomCommandsInfo)); ClassicAssert.IsNotNull(respCustomCommandsInfo); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, enableAOF: true, lowMemory: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true, lowMemory: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } [Test] - public void AofUpsertStoreRecoverTest() + public async Task AofUpsertStoreRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -60,9 +63,10 @@ public void AofUpsertStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -75,7 +79,7 @@ public void AofUpsertStoreRecoverTest() } [Test] - public void AofUpsertStoreAutoCommitRecoverTest() + public async Task AofUpsertStoreAutoCommitRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -85,9 +89,10 @@ public void AofUpsertStoreAutoCommitRecoverTest() } server.Store.WaitForCommit(); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -101,11 +106,12 @@ public void AofUpsertStoreAutoCommitRecoverTest() [Test] [CancelAfter(10_000)] - public void AofUpsertStoreCommitTaskRecoverTest() + public async Task AofUpsertStoreCommitTaskRecoverTest() { - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitFrequencyMs: 100); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitFrequencyMs: 100); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -115,9 +121,10 @@ public void AofUpsertStoreCommitTaskRecoverTest() } server.Store.WaitForCommit(); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -130,11 +137,12 @@ public void AofUpsertStoreCommitTaskRecoverTest() } [Test] - public void AofUpsertStoreAutoCommitCommitWaitRecoverTest() + public async Task AofUpsertStoreAutoCommitCommitWaitRecoverTest() { - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitWait: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitWait: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -142,9 +150,10 @@ public void AofUpsertStoreAutoCommitCommitWaitRecoverTest() db.StringSet("SeAofUpsertRecoverTestKey1", "SeAofUpsertRecoverTestValue1"); db.StringSet("SeAofUpsertRecoverTestKey2", "SeAofUpsertRecoverTestValue2"); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -157,11 +166,12 @@ public void AofUpsertStoreAutoCommitCommitWaitRecoverTest() } [Test] - public void AofTransactionStoreAutoCommitCommitWaitRecoverTest() + public async Task AofTransactionStoreAutoCommitCommitWaitRecoverTest() { - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitWait: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: false, enableAOF: true, commitWait: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -172,9 +182,10 @@ public void AofTransactionStoreAutoCommitCommitWaitRecoverTest() ClassicAssert.IsTrue(transaction.Execute()); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -187,7 +198,7 @@ public void AofTransactionStoreAutoCommitCommitWaitRecoverTest() } [Test] - public void AofUpsertStoreCkptRecoverTest() + public async Task AofUpsertStoreCkptRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -205,9 +216,10 @@ public void AofUpsertStoreCkptRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -222,7 +234,7 @@ public void AofUpsertStoreCkptRecoverTest() } [Test] - public void AofRMWStoreRecoverTest() + public async Task AofRMWStoreRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -236,9 +248,10 @@ public void AofRMWStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -254,7 +267,7 @@ public void AofRMWStoreRecoverTest() } [Test] - public void AofDeleteStoreRecoverTest() + public async Task AofDeleteStoreRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -274,9 +287,10 @@ public void AofDeleteStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -291,7 +305,7 @@ public void AofDeleteStoreRecoverTest() } [Test] - public void AofExpiryRMWStoreRecoverTest() + public async Task AofExpiryRMWStoreRecoverTest() { using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -309,9 +323,10 @@ public void AofExpiryRMWStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -324,7 +339,7 @@ public void AofExpiryRMWStoreRecoverTest() } [Test] - public void AofRMWObjectStoreRecoverTest() + public async Task AofRMWObjectStoreRecoverTest() { var key = "AofRMWObjectStoreRecoverTestKey"; @@ -343,9 +358,10 @@ public void AofRMWObjectStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -361,7 +377,7 @@ public void AofRMWObjectStoreRecoverTest() } [Test] - public void AofDeleteObjectStoreRecoverTest() + public async Task AofDeleteObjectStoreRecoverTest() { var key1 = "AofDeleteObjectStoreRecoverTestKey1"; var key2 = "AofDeleteObjectStoreRecoverTestKey2"; @@ -389,9 +405,10 @@ public void AofDeleteObjectStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -404,7 +421,7 @@ public void AofDeleteObjectStoreRecoverTest() } [Test] - public void AofRMWObjectStoreCopyUpdateRecoverTest() + public async Task AofRMWObjectStoreCopyUpdateRecoverTest() { var key = "AofRMWObjectStoreRecoverTestKey"; @@ -425,9 +442,10 @@ public void AofRMWObjectStoreCopyUpdateRecoverTest() db.SortedSetAdd("AofRMWObjectStoreRecoverTestKey" + 1, newEntries); } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -443,7 +461,7 @@ public void AofRMWObjectStoreCopyUpdateRecoverTest() } [Test] - public void AofUpsertObjectStoreRecoverTest() + public async Task AofUpsertObjectStoreRecoverTest() { var origList = new RedisValue[] { "a", "b", "c", "d" }; var key1 = "lkey1"; @@ -468,9 +486,10 @@ public void AofUpsertObjectStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -482,19 +501,20 @@ public void AofUpsertObjectStoreRecoverTest() } [Test] - public void AofUpsertCustomObjectRecoverTest() + public async Task AofUpsertCustomObjectRecoverTest() { - void RegisterCustomCommand(GarnetServer gServer) + void RegisterCustomCommand(GarnetApplication gServer) { var factory = new MyDictFactory(); gServer.Register.NewCommand("MYDICTSET", CommandType.ReadModifyWrite, factory, new MyDictSet(), respCustomCommandsInfo["MYDICTSET"]); gServer.Register.NewCommand("MYDICTGET", CommandType.Read, factory, new MyDictGet(), respCustomCommandsInfo["MYDICTGET"]); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, enableAOF: true); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true); RegisterCustomCommand(server); - server.Start(); + await server.RunAsync(); var mainKey1 = "key1"; var subKey = "subKey"; @@ -518,10 +538,11 @@ void RegisterCustomCommand(GarnetServer gServer) } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); RegisterCustomCommand(server); - server.Start(); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -533,7 +554,7 @@ void RegisterCustomCommand(GarnetServer gServer) } [Test] - public void AofUpsertCustomScriptRecoverTest() + public async Task AofUpsertCustomScriptRecoverTest() { static void ValidateServerData(IDatabase db, string strKey, string strValue, string listKey, string listValue) { @@ -544,10 +565,11 @@ static void ValidateServerData(IDatabase db, string strKey, string strValue, str ClassicAssert.AreEqual(listValue, (string)retList[0]); } - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, enableAOF: true); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableAOF: true); server.Register.NewProcedure("SETMAINANDOBJECT", () => new SetStringAndList()); - server.Start(); + await server.RunAsync(); var strKey = "StrKey"; var strValue = "StrValue"; @@ -562,10 +584,11 @@ static void ValidateServerData(IDatabase db, string strKey, string strValue, str } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); server.Register.NewProcedure("SETMAINANDOBJECT", () => new SetStringAndList()); - server.Start(); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -574,7 +597,7 @@ static void ValidateServerData(IDatabase db, string strKey, string strValue, str } [Test] - public void AofMultiRMWStoreCkptRecoverTest() + public async Task AofMultiRMWStoreCkptRecoverTest() { long ret = 0; using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) @@ -611,9 +634,10 @@ public void AofMultiRMWStoreCkptRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig(allowAdmin: true))) { @@ -624,7 +648,7 @@ public void AofMultiRMWStoreCkptRecoverTest() } [Test] - public void AofListObjectStoreRecoverTest() + public async Task AofListObjectStoreRecoverTest() { var key = "AofListObjectStoreRecoverTest"; var ldata = new RedisValue[] { "a", "b", "c", "d" }; @@ -642,9 +666,10 @@ public void AofListObjectStoreRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); - server.Start(); + await server.StopAsync(); + server.Dispose(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { @@ -656,7 +681,7 @@ public void AofListObjectStoreRecoverTest() } [Test] - public void AofCustomTxnRecoverTest() + public async Task AofCustomTxnRecoverTest() { server.Register.NewTransactionProc("READWRITETX", () => new ReadWriteTxn(), new RespCommandsInfo { Arity = 4 }); string readkey = "readme"; @@ -676,11 +701,12 @@ public void AofCustomTxnRecoverTest() } server.Store.CommitAOF(true); - server.Dispose(false); + await server.StopAsync(); + server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, tryRecover: true, enableAOF: true); server.Register.NewTransactionProc("READWRITETX", () => new ReadWriteTxn(), new RespCommandsInfo { Arity = 4 }); - server.Start(); + await server.RunAsync(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { diff --git a/test/Garnet.test/RespBlockingCollectionTests.cs b/test/Garnet.test/RespBlockingCollectionTests.cs index 6292038e48..2add91147f 100644 --- a/test/Garnet.test/RespBlockingCollectionTests.cs +++ b/test/Garnet.test/RespBlockingCollectionTests.cs @@ -12,20 +12,21 @@ namespace Garnet.test { public class RespBlockingCollectionTests { - GarnetServer server; + GarnetApplication server; private TaskFactory taskFactory = new(); [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespCommandTests.cs b/test/Garnet.test/RespCommandTests.cs index 76ba19d6c1..22985b345f 100644 --- a/test/Garnet.test/RespCommandTests.cs +++ b/test/Garnet.test/RespCommandTests.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Reflection; using System.Runtime.InteropServices; +using System.Threading.Tasks; using Garnet.common; using Garnet.server; using NUnit.Framework; @@ -21,7 +22,7 @@ namespace Garnet.test [TestFixture] public class RespCommandTests { - GarnetServer server; + GarnetApplication server; private string extTestDir; private IReadOnlyDictionary respCommandsInfo; private IReadOnlyDictionary externalRespCommandsInfo; @@ -51,7 +52,7 @@ public class RespCommandTests ]; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); extTestDir = Path.Combine(TestUtils.MethodTestDir, "test"); @@ -75,14 +76,15 @@ .. respCommandsInfo.Values.Where(ci => ci.IsInternal).Select(ci => ci.Command) .Union(respSubCommandsInfo.Values.Where(sc => sc.IsInternal).Select(sc => sc.Command)) ]; - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, disablePubSub: true, + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, disablePubSub: true, extensionBinPaths: [extTestDir]); - server.Start(); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); TestUtils.DeleteDirectory(Directory.GetParent(extTestDir)?.FullName); diff --git a/test/Garnet.test/RespCustomCommandTests.cs b/test/Garnet.test/RespCustomCommandTests.cs index 7e4752c3e0..e2d089939a 100644 --- a/test/Garnet.test/RespCustomCommandTests.cs +++ b/test/Garnet.test/RespCustomCommandTests.cs @@ -225,27 +225,28 @@ public override unsafe void Main(TGarnetApi garnetApi, ref CustomPro [TestFixture] public class RespCustomCommandTests { - GarnetServer server; + GarnetApplication server; private string _extTestDir1; private string _extTestDir2; [SetUp] - public void Setup() + public async Task Setup() { _extTestDir1 = Path.Combine(TestUtils.MethodTestDir, "test1"); _extTestDir2 = Path.Combine(TestUtils.MethodTestDir, "test2"); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, disablePubSub: true, extensionBinPaths: [_extTestDir1, _extTestDir2], extensionAllowUnsignedAssemblies: true); - server.Start(); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); TestUtils.DeleteDirectory(Directory.GetParent(_extTestDir1)?.FullName); diff --git a/test/Garnet.test/RespEtagTests.cs b/test/Garnet.test/RespEtagTests.cs index 3bd15c489e..fd75795e34 100644 --- a/test/Garnet.test/RespEtagTests.cs +++ b/test/Garnet.test/RespEtagTests.cs @@ -16,21 +16,22 @@ namespace Garnet.test [TestFixture] public class RespEtagTests { - private GarnetServer server; + private GarnetApplication server; private Random r; [SetUp] - public void Setup() + public async Task Setup() { r = new Random(674386); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, disablePubSub: false); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, disablePubSub: false); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } @@ -976,13 +977,13 @@ public void SingleDeleteForEtagSetData() } [Test] - public void SingleDeleteWithObjectStoreDisabledForEtagSetData() + public async Task SingleDeleteWithObjectStoreDisabledForEtagSetData() { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: true); + await server.RunAsync(); var key = "delKey"; var value = "1234"; @@ -1009,13 +1010,13 @@ private string GetRandomString(int len) } [Test] - public void SingleDeleteWithObjectStoreDisable_LTMForEtagSetData() + public async Task SingleDeleteWithObjectStoreDisable_LTMForEtagSetData() { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, DisableObjects: true); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -1049,14 +1050,14 @@ public void SingleDeleteWithObjectStoreDisable_LTMForEtagSetData() } [Test] - public void MultiKeyDeleteForEtagSetData([Values] bool withoutObjectStore) + public async Task MultiKeyDeleteForEtagSetData([Values] bool withoutObjectStore) { if (withoutObjectStore) { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: true); + await server.RunAsync(); } using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); @@ -1084,14 +1085,14 @@ public void MultiKeyDeleteForEtagSetData([Values] bool withoutObjectStore) } [Test] - public void MultiKeyUnlinkForEtagSetData([Values] bool withoutObjectStore) + public async Task MultiKeyUnlinkForEtagSetData([Values] bool withoutObjectStore) { if (withoutObjectStore) { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: true); + await server.RunAsync(); } using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); @@ -1118,14 +1119,14 @@ public void MultiKeyUnlinkForEtagSetData([Values] bool withoutObjectStore) } [Test] - public void SingleExistsForEtagSetData([Values] bool withoutObjectStore) + public async Task SingleExistsForEtagSetData([Values] bool withoutObjectStore) { if (withoutObjectStore) { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: true); + await server.RunAsync(); } using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); diff --git a/test/Garnet.test/RespGetLowMemoryTests.cs b/test/Garnet.test/RespGetLowMemoryTests.cs index ff39389a7e..dd89f0c792 100644 --- a/test/Garnet.test/RespGetLowMemoryTests.cs +++ b/test/Garnet.test/RespGetLowMemoryTests.cs @@ -14,21 +14,22 @@ namespace Garnet.test [TestFixture] public class RespGetLowMemoryTests { - GarnetServer server; + GarnetApplication server; Random r; [SetUp] - public void Setup() + public async Task Setup() { r = new Random(335); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true, getSG: true, disablePubSub: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, getSG: true, disablePubSub: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespHashTests.cs b/test/Garnet.test/RespHashTests.cs index d162db0f0c..e79e5472c3 100644 --- a/test/Garnet.test/RespHashTests.cs +++ b/test/Garnet.test/RespHashTests.cs @@ -16,21 +16,22 @@ namespace Garnet.test [TestFixture] public class RespHashTests { - GarnetServer server; + GarnetApplication server; static readonly HashEntry[] entries = new HashEntry[100]; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, enableReadCache: true, enableObjectStoreReadCache: true, lowMemory: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, enableReadCache: true, enableObjectStoreReadCache: true, lowMemory: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespInfoTests.cs b/test/Garnet.test/RespInfoTests.cs index c6c5e077f9..b3df9e9ebc 100644 --- a/test/Garnet.test/RespInfoTests.cs +++ b/test/Garnet.test/RespInfoTests.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using System.Threading; +using System.Threading.Tasks; using NUnit.Framework; using NUnit.Framework.Legacy; using StackExchange.Redis; @@ -13,21 +14,22 @@ namespace Garnet.test [TestFixture] public class RespInfoTests { - GarnetServer server; + GarnetApplication server; Random r; [SetUp] - public void Setup() + public async Task Setup() { r = new Random(674386); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, disablePubSub: true, latencyMonitor: true, metricsSamplingFreq: 1, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, disablePubSub: true, latencyMonitor: true, metricsSamplingFreq: 1, DisableObjects: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } @@ -53,7 +55,7 @@ public void ResetStatsTest() infoResult = db.Execute("INFO").ToString(); infoResultArr = infoResult.Split("\r\n"); totalFound = infoResultArr.First(x => x.StartsWith("total_found")); - ClassicAssert.AreEqual("total_found:1", totalFound, "Expected total_foudn to be incremented to 1 after a successful request."); + ClassicAssert.AreEqual("total_found:1", totalFound, "Expected total_found to be incremented to 1 after a successful request."); var result = db.Execute("INFO", "RESET"); ClassicAssert.IsNotNull(result); diff --git a/test/Garnet.test/RespListGarnetClientTests.cs b/test/Garnet.test/RespListGarnetClientTests.cs index 44137a37e3..0e8239167e 100644 --- a/test/Garnet.test/RespListGarnetClientTests.cs +++ b/test/Garnet.test/RespListGarnetClientTests.cs @@ -12,14 +12,14 @@ namespace Garnet.test [TestFixture] public class RespListGarnetClientTests { - private GarnetServer server; + private GarnetApplication server; [OneTimeSetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true); + await server.RunAsync(); } private static object[] LeftPushTestCases = @@ -271,8 +271,9 @@ private static async Task ValidateListContentAsync(GarnetClient db, string key, } [OneTimeTearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); diff --git a/test/Garnet.test/RespListTests.cs b/test/Garnet.test/RespListTests.cs index 286f7b9dfa..be9c64f7ab 100644 --- a/test/Garnet.test/RespListTests.cs +++ b/test/Garnet.test/RespListTests.cs @@ -17,21 +17,22 @@ namespace Garnet.test [TestFixture] class RespListTests { - GarnetServer server; + GarnetApplication server; Random r; [SetUp] - public void Setup() + public async Task Setup() { r = new Random(674386); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespLowMemoryTests.cs b/test/Garnet.test/RespLowMemoryTests.cs index 091d100637..33a06d8f18 100644 --- a/test/Garnet.test/RespLowMemoryTests.cs +++ b/test/Garnet.test/RespLowMemoryTests.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using System; +using System.Threading.Tasks; using NUnit.Framework; using NUnit.Framework.Legacy; using StackExchange.Redis; @@ -11,19 +12,20 @@ namespace Garnet.test [TestFixture] public class RespLowMemoryTests { - GarnetServer server; + GarnetApplication server; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespMetricsTest.cs b/test/Garnet.test/RespMetricsTest.cs index 024cd94954..a7581a2f2e 100644 --- a/test/Garnet.test/RespMetricsTest.cs +++ b/test/Garnet.test/RespMetricsTest.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using System.Threading; +using System.Threading.Tasks; using Garnet.common; using Microsoft.Extensions.Logging; using NUnit.Framework; @@ -15,14 +16,14 @@ namespace Garnet.test [TestFixture] public class RespMetricsTest { - GarnetServer server; + GarnetApplication server; ILoggerFactory loggerFactory; Random r; - private void StartServer(int metricsSamplingFreq = -1, bool latencyMonitor = false) + private async Task StartServer(int metricsSamplingFreq = -1, bool latencyMonitor = false) { - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, metricsSamplingFreq: metricsSamplingFreq, latencyMonitor: latencyMonitor); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, metricsSamplingFreq: metricsSamplingFreq, latencyMonitor: latencyMonitor); + await server.RunAsync(); } [SetUp] @@ -35,16 +36,20 @@ public void Setup() } [TearDown] - public void TearDown() + public async Task TearDown() { - server?.Dispose(); + if (server != null) + { + await server.StopAsync(); + server.Dispose(); + } TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); } [Test] - public void MetricsDisabledTest() + public async Task MetricsDisabledTest() { - StartServer(); + await StartServer(); var logger = loggerFactory.CreateLogger(TestContext.CurrentContext.Test.Name); var infoMetrics = server.Metrics.GetInfoMetrics().ToArray(); @@ -71,9 +76,9 @@ public void MetricsDisabledTest() } [Test] - public void MetricsEnabledTest() + public async Task MetricsEnabledTest() { - StartServer(1, true); + await StartServer(1, true); var logger = loggerFactory.CreateLogger(TestContext.CurrentContext.Test.Name); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); diff --git a/test/Garnet.test/RespModuleTests.cs b/test/Garnet.test/RespModuleTests.cs index 47a5075b53..c70a799f93 100644 --- a/test/Garnet.test/RespModuleTests.cs +++ b/test/Garnet.test/RespModuleTests.cs @@ -4,6 +4,7 @@ using System.IO; using System.Reflection; using System.Runtime.InteropServices; +using System.Threading.Tasks; using NUnit.Framework; using NUnit.Framework.Legacy; using StackExchange.Redis; @@ -13,26 +14,27 @@ namespace Garnet.test [TestFixture] public class RespModuleTests { - GarnetServer server; + GarnetApplication server; private string testModuleDir; string binPath; [SetUp] - public void Setup() + public async Task Setup() { testModuleDir = Path.Combine(TestUtils.MethodTestDir, "testModules"); binPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, disablePubSub: true, extensionBinPaths: [testModuleDir, binPath], extensionAllowUnsignedAssemblies: true); - server.Start(); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); TestUtils.DeleteDirectory(Directory.GetParent(testModuleDir)?.FullName); @@ -176,7 +178,7 @@ public void TestModuleLoad() [Test] - public void TestModuleLoadUsingGarnetOptions() + public async Task TestModuleLoadUsingGarnetOptions() { var onLoad = @"context.Initialize(""TestModule1"", 1); @@ -192,11 +194,12 @@ public void TestModuleLoadUsingGarnetOptions() var module1Path = CreateTestModule(onLoad, "TestModule1.dll"); var module2Path = CreateTestModule(onLoad2, "TestModule2.dll"); + await server.StopAsync(); server.Dispose(); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, disablePubSub: true, loadModulePaths: [module1Path, module2Path]); - server.Start(); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); diff --git a/test/Garnet.test/RespPubSubTests.cs b/test/Garnet.test/RespPubSubTests.cs index 35b1d63168..fb6197e5ca 100644 --- a/test/Garnet.test/RespPubSubTests.cs +++ b/test/Garnet.test/RespPubSubTests.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Security.Cryptography; using System.Threading; +using System.Threading.Tasks; using NUnit.Framework; using NUnit.Framework.Legacy; using StackExchange.Redis; @@ -14,19 +15,20 @@ namespace Garnet.test [TestFixture] class RespPubSubTests { - GarnetServer server; + GarnetApplication server; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, pubSubPageSize: "256k"); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, pubSubPageSize: "256k"); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespScanCommandsTests.cs b/test/Garnet.test/RespScanCommandsTests.cs index bba4077d18..173f6ba270 100644 --- a/test/Garnet.test/RespScanCommandsTests.cs +++ b/test/Garnet.test/RespScanCommandsTests.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading.Tasks; using Garnet.server; using NUnit.Framework; using NUnit.Framework.Legacy; @@ -15,22 +16,23 @@ namespace Garnet.test [TestFixture] public class RespScanCommandsTests { - GarnetServer server; + GarnetApplication server; private IReadOnlyDictionary respCustomCommandsInfo; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); ClassicAssert.IsTrue(TestUtils.TryGetCustomCommandsInfo(out respCustomCommandsInfo)); ClassicAssert.IsNotNull(respCustomCommandsInfo); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespSetTest.cs b/test/Garnet.test/RespSetTest.cs index fbb1eae1ec..0ceeb3e214 100644 --- a/test/Garnet.test/RespSetTest.cs +++ b/test/Garnet.test/RespSetTest.cs @@ -17,19 +17,20 @@ namespace Garnet.test [TestFixture] public class RespSetTest { - GarnetServer server; + GarnetApplication server; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespSortedSetGarnetClientTests.cs b/test/Garnet.test/RespSortedSetGarnetClientTests.cs index ef7d456381..e8c0a97678 100644 --- a/test/Garnet.test/RespSortedSetGarnetClientTests.cs +++ b/test/Garnet.test/RespSortedSetGarnetClientTests.cs @@ -21,7 +21,7 @@ namespace Garnet.test [TestFixture] public class RespSortedSetGarnetClientTests { - protected GarnetServer server; + protected GarnetApplication server; ManualResetEventSlim waiter; const int maxIterations = 3; @@ -41,18 +41,19 @@ public class RespSortedSetGarnetClientTests [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true, enableAOF: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, enableAOF: true); + await server.RunAsync(); waiter = new ManualResetEventSlim(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespSortedSetGeoTests.cs b/test/Garnet.test/RespSortedSetGeoTests.cs index b7c6d1cc88..84f93f8c4e 100644 --- a/test/Garnet.test/RespSortedSetGeoTests.cs +++ b/test/Garnet.test/RespSortedSetGeoTests.cs @@ -5,6 +5,7 @@ using System.Globalization; using System.Linq; using System.Text; +using System.Threading.Tasks; using Garnet.common; using Garnet.server; using NUnit.Framework; @@ -16,7 +17,7 @@ namespace Garnet.test [TestFixture] public class RespSortedSetGeoTests { - GarnetServer server; + GarnetApplication server; readonly string[,] cities = new string[,] { {"-74.0059413", "40.7127837", "New York"}, {"-118.2436849", "34.0522342", "Los Angeles"}, @@ -126,16 +127,17 @@ public class RespSortedSetGeoTests [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespSortedSetTests.cs b/test/Garnet.test/RespSortedSetTests.cs index 3abfaa67c2..385057ad54 100644 --- a/test/Garnet.test/RespSortedSetTests.cs +++ b/test/Garnet.test/RespSortedSetTests.cs @@ -27,7 +27,7 @@ namespace Garnet.test [TestFixture] public class RespSortedSetTests { - protected GarnetServer server; + protected GarnetApplication server; static readonly SortedSetEntry[] entries = [ @@ -73,17 +73,18 @@ public class RespSortedSetTests [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespTests.cs b/test/Garnet.test/RespTests.cs index 8e45ccba29..ab0d1d0ee3 100644 --- a/test/Garnet.test/RespTests.cs +++ b/test/Garnet.test/RespTests.cs @@ -22,22 +22,23 @@ namespace Garnet.test [TestFixture] public class RespTests { - GarnetServer server; + GarnetApplication server; Random r; private TaskFactory taskFactory = new(); [SetUp] - public void Setup() + public async Task Setup() { r = new Random(674386); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, disablePubSub: false); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, disablePubSub: false); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } @@ -1382,13 +1383,13 @@ public void SingleDelete() } [Test] - public void SingleDeleteWithObjectStoreDisabled() + public async Task SingleDeleteWithObjectStoreDisabled() { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: true); + await server.RunAsync(); var key = "delKey"; var value = "1234"; @@ -1414,13 +1415,13 @@ private string GetRandomString(int len) } [Test] - public void SingleDeleteWithObjectStoreDisable_LTM() + public async Task SingleDeleteWithObjectStoreDisable_LTM() { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, DisableObjects: true); + await server.RunAsync(); using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -1454,14 +1455,14 @@ public void SingleDeleteWithObjectStoreDisable_LTM() } [Test] - public void MultiKeyDelete([Values] bool withoutObjectStore) + public async Task MultiKeyDelete([Values] bool withoutObjectStore) { if (withoutObjectStore) { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: true); + await server.RunAsync(); } using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); @@ -1522,14 +1523,14 @@ public void MultiKeyDeleteObjectStore() } [Test] - public void MultiKeyUnlink([Values] bool withoutObjectStore) + public async Task MultiKeyUnlink([Values] bool withoutObjectStore) { if (withoutObjectStore) { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: true); + await server.RunAsync(); } using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); @@ -1588,14 +1589,14 @@ public void MultiKeyUnlinkObjectStore() } [Test] - public void SingleExists([Values] bool withoutObjectStore) + public async Task SingleExists([Values] bool withoutObjectStore) { if (withoutObjectStore) { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: true); + await server.RunAsync(); } using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -1853,14 +1854,14 @@ public void SingleRenameWithExpiry() } [Test] - public void SingleRenameKeyEdgeCase([Values] bool withoutObjectStore) + public async Task SingleRenameKeyEdgeCase([Values] bool withoutObjectStore) { if (withoutObjectStore) { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, DisableObjects: true); + await server.RunAsync(); } using var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig()); var db = redis.GetDatabase(0); @@ -3753,13 +3754,13 @@ public void HelloTest1() } [Test] - public void AsyncTest1() + public async Task AsyncTest1() { // Set up low-memory database - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true, DisableObjects: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true, DisableObjects: true); + await server.RunAsync(); string firstKey = null, firstValue = null, lastKey = null, lastValue = null; diff --git a/test/Garnet.test/RespTlsTests.cs b/test/Garnet.test/RespTlsTests.cs index 7e61240516..7c1b4e3dd7 100644 --- a/test/Garnet.test/RespTlsTests.cs +++ b/test/Garnet.test/RespTlsTests.cs @@ -17,19 +17,20 @@ namespace Garnet.test [TestFixture] public class RespTlsTests { - GarnetServer server; + GarnetApplication server; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, EnableTLS: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, EnableTLS: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/RespTransactionProcTests.cs b/test/Garnet.test/RespTransactionProcTests.cs index b3f3c05c29..bf0eb03765 100644 --- a/test/Garnet.test/RespTransactionProcTests.cs +++ b/test/Garnet.test/RespTransactionProcTests.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using System.Threading; +using System.Threading.Tasks; using Garnet.server; using NUnit.Framework; using NUnit.Framework.Legacy; @@ -12,19 +13,20 @@ namespace Garnet.test [TestFixture] public class RespTransactionProcTests { - GarnetServer server; + GarnetApplication server; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, disablePubSub: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, disablePubSub: true); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } diff --git a/test/Garnet.test/TestUtils.cs b/test/Garnet.test/TestUtils.cs index fbca671df8..9b1a6dafec 100644 --- a/test/Garnet.test/TestUtils.cs +++ b/test/Garnet.test/TestUtils.cs @@ -180,9 +180,9 @@ internal static void IgnoreIfNotRunningAzureTests() } /// - /// Create GarnetServer + /// Create GarnetApplication /// - public static GarnetServer CreateGarnetServer( + public static GarnetApplication CreateGarnetApplication( string logCheckpointDir, bool disablePubSub = false, bool tryRecover = false, @@ -333,17 +333,25 @@ public static GarnetServer CreateGarnetServer( if (useTestLogger) { - var loggerFactory = LoggerFactory.Create(builder => - { - builder.AddProvider(new NUnitLoggerProvider(TestContext.Progress, TestContext.CurrentContext.Test.MethodName, null, false, false, LogLevel.Trace)); - builder.SetMinimumLevel(LogLevel.Trace); - }); + var builder = GarnetApplication.CreateHostBuilder([], opts); + + builder.Logging.ClearProviders(); + builder.Logging.AddProvider(new NUnitLoggerProvider(TestContext.Progress, + TestContext.CurrentContext.Test.MethodName, null, false, false, LogLevel.Trace)); + builder.Logging.SetMinimumLevel(LogLevel.Trace); + + var app = builder.Build(); - return new GarnetServer(opts, loggerFactory); + return app; } else { - return new GarnetServer(opts); + + var builder = GarnetApplication.CreateHostBuilder([], opts); + + var app = builder.Build(); + + return app; } } @@ -367,7 +375,7 @@ public static ILoggerFactory CreateLoggerFactoryInstance(TextWriter textWriter, }); } - public static GarnetServer[] CreateGarnetCluster( + public static GarnetApplication[] CreateGarnetCluster( string checkpointDir, EndPointCollection endpoints, bool disablePubSub = false, @@ -405,7 +413,7 @@ public static GarnetServer[] CreateGarnetCluster( { if (UseAzureStorage) IgnoreIfNotRunningAzureTests(); - GarnetServer[] nodes = new GarnetServer[endpoints.Count]; + var nodes = new GarnetApplication[endpoints.Count]; for (int i = 0; i < nodes.Length; i++) { IPEndPoint endpoint = (IPEndPoint)endpoints[i]; @@ -455,7 +463,13 @@ public static GarnetServer[] CreateGarnetCluster( TestContext.Progress.WriteLine($"Waiting for Port {opts.Port} to become available for {TestContext.CurrentContext.WorkerId}:{iter++}"); Thread.Sleep(1000); } - nodes[i] = new GarnetServer(opts, loggerFactory); + + var builder = GarnetApplication.CreateHostBuilder([], opts); + + var app = builder.Build(); + + nodes[i] = app; + } return nodes; } diff --git a/test/Garnet.test/TransactionTests.cs b/test/Garnet.test/TransactionTests.cs index aefd400cdc..bb6beccab2 100644 --- a/test/Garnet.test/TransactionTests.cs +++ b/test/Garnet.test/TransactionTests.cs @@ -13,29 +13,30 @@ namespace Garnet.test [TestFixture] public class TransactionTests { - GarnetServer server; + GarnetApplication server; [SetUp] - public void Setup() + public async Task Setup() { TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir); + await server.RunAsync(); } [TearDown] - public void TearDown() + public async Task TearDown() { + await server.StopAsync(); server.Dispose(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir); } - public void SetUpWithLowMemory() + public async Task SetUpWithLowMemory() { - TearDown(); + await TearDown(); TestUtils.DeleteDirectory(TestUtils.MethodTestDir, wait: true); - server = TestUtils.CreateGarnetServer(TestUtils.MethodTestDir, lowMemory: true); - server.Start(); + server = TestUtils.CreateGarnetApplication(TestUtils.MethodTestDir, lowMemory: true); + await server.RunAsync(); } [Test] @@ -323,7 +324,7 @@ public async Task WatchNonExistentKey() [Test] public async Task WatchKeyFromDisk() { - SetUpWithLowMemory(); + await SetUpWithLowMemory(); using (var redis = ConnectionMultiplexer.Connect(TestUtils.GetConfig())) { var db = redis.GetDatabase(0);