public async Task DisconnectWhenAConnectIsInProgress() { // Arrange var circuitIdFactory = TestCircuitIdFactory.CreateTestFactory(); var registry = new TestCircuitRegistry(circuitIdFactory); registry.BeforeConnect = new ManualResetEventSlim(); var circuitHost = TestCircuitHost.Create(circuitIdFactory.CreateCircuitId()); registry.Register(circuitHost); var client = Mock.Of <IClientProxy>(); var oldId = circuitHost.Client.ConnectionId; var newId = "new-connection"; // Act var connect = Task.Run(() => registry.ConnectAsync(circuitHost.CircuitId, client, newId, default)); var disconnect = Task.Run(() => registry.DisconnectAsync(circuitHost, oldId)); registry.BeforeConnect.Set(); await Task.WhenAll(connect, disconnect); // Assert // We expect the disconnect to fail since the client identifier has changed. var actual = Assert.Single(registry.ConnectedCircuits.Values); Assert.Same(circuitHost, actual); Assert.Same(client, circuitHost.Client.Client); Assert.Equal(newId, circuitHost.Client.ConnectionId); Assert.False(registry.DisconnectedCircuits.TryGetValue(circuitHost.CircuitId, out _)); }
public async Task ReconnectBeforeTimeoutDoesNotGetEntryToBeEvicted() { // Arrange var circuitIdFactory = TestCircuitIdFactory.CreateTestFactory(); var circuitOptions = new CircuitOptions { DisconnectedCircuitRetentionPeriod = TimeSpan.FromSeconds(8), }; var registry = new TestCircuitRegistry(circuitIdFactory, circuitOptions); var tcs = new TaskCompletionSource <object>(); registry.OnAfterEntryEvicted = () => { tcs.TrySetResult(new object()); }; var circuitHost = TestCircuitHost.Create(circuitIdFactory.CreateCircuitId()); registry.RegisterDisconnectedCircuit(circuitHost); await registry.ConnectAsync(circuitHost.CircuitId, Mock.Of <IClientProxy>(), "new-connection", default); // Act await Task.Run(() => tcs.Task.TimeoutAfter(TimeSpan.FromSeconds(10))); // Verify it's still connected Assert.True(registry.ConnectedCircuits.TryGetValue(circuitHost.CircuitId, out var cacheValue)); Assert.Same(circuitHost, cacheValue); // Nothing should be disconnected. Assert.False(registry.DisconnectedCircuits.TryGetValue(circuitHost.CircuitId.Secret, out var _)); }
public async Task DisconnectedCircuitIsRemovedAfterConfiguredTimeout() { // Arrange var circuitIdFactory = TestCircuitIdFactory.CreateTestFactory(); var circuitOptions = new CircuitOptions { DisconnectedCircuitRetentionPeriod = TimeSpan.FromSeconds(3), }; var registry = new TestCircuitRegistry(circuitIdFactory, circuitOptions); var tcs = new TaskCompletionSource <object>(); registry.OnAfterEntryEvicted = () => { tcs.TrySetResult(new object()); }; var circuitHost = TestCircuitHost.Create(); registry.RegisterDisconnectedCircuit(circuitHost); // Act // Verify it's present in the dictionary. Assert.True(registry.DisconnectedCircuits.TryGetValue(circuitHost.CircuitId.Secret, out var _)); await Task.Run(() => tcs.Task.TimeoutAfter(TimeSpan.FromSeconds(10))); Assert.False(registry.DisconnectedCircuits.TryGetValue(circuitHost.CircuitId.Secret, out var _)); }
public void CircuitRegistryUsesConfiguredMaxRetainedDisconnectedCircuitsValue() { // Arrange var circuitIdFactory = TestCircuitIdFactory.CreateTestFactory(); var maxCircuits = 3; var circuitOptions = new CircuitOptions { MaxRetainedDisconnectedCircuits = maxCircuits, }; var registry = new TestCircuitRegistry(circuitIdFactory, circuitOptions); var hosts = Enumerable.Range(0, maxCircuits + 2) .Select(_ => TestCircuitHost.Create()) .ToArray(); // Act for (var i = 0; i < hosts.Length; i++) { registry.RegisterDisconnectedCircuit(hosts[i]); } // Assert for (var i = 0; i < maxCircuits; i++) { Assert.True(registry.DisconnectedCircuits.TryGetValue(hosts[i].CircuitId, out var _)); } // Additional circuits do not get registered. Assert.False(registry.DisconnectedCircuits.TryGetValue(hosts[maxCircuits].CircuitId, out var _)); Assert.False(registry.DisconnectedCircuits.TryGetValue(hosts[maxCircuits + 1].CircuitId, out var _)); }
public async Task Connect_WhileDisconnectIsInProgress() { // Arrange var circuitIdFactory = TestCircuitIdFactory.CreateTestFactory(); var registry = new TestCircuitRegistry(circuitIdFactory); registry.BeforeDisconnect = new ManualResetEventSlim(); var tcs = new TaskCompletionSource <int>(); var circuitHost = TestCircuitHost.Create(circuitIdFactory.CreateCircuitId()); registry.Register(circuitHost); var client = Mock.Of <IClientProxy>(); var newId = "new-connection"; // Act var disconnect = Task.Run(() => { var task = registry.DisconnectAsync(circuitHost, circuitHost.Client.ConnectionId); tcs.SetResult(0); return(task); }); var connect = Task.Run(async() => { registry.BeforeDisconnect.Set(); await tcs.Task; await registry.ConnectAsync(circuitHost.CircuitId, client, newId, default); }); registry.BeforeDisconnect.Set(); await Task.WhenAll(disconnect, connect); // Assert // We expect the disconnect to finish followed by a reconnect var actual = Assert.Single(registry.ConnectedCircuits.Values); Assert.Same(circuitHost, actual); Assert.Same(client, circuitHost.Client.Client); Assert.Equal(newId, circuitHost.Client.ConnectionId); Assert.False(registry.DisconnectedCircuits.TryGetValue(circuitHost.CircuitId, out _)); }
public async Task Connect_WhileDisconnectIsInProgress_SeriallyExecutesCircuitHandlers() { // Arrange var circuitIdFactory = TestCircuitIdFactory.CreateTestFactory(); var registry = new TestCircuitRegistry(circuitIdFactory); registry.BeforeDisconnect = new ManualResetEventSlim(); // This verifies that connection up \ down events on a circuit handler are always invoked serially. var circuitHandler = new SerialCircuitHandler(); var tcs = new TaskCompletionSource <int>(); var circuitHost = TestCircuitHost.Create(circuitIdFactory.CreateCircuitId(), handlers: new[] { circuitHandler }); registry.Register(circuitHost); var client = Mock.Of <IClientProxy>(); var newId = "new-connection"; // Act var disconnect = Task.Run(() => { var task = registry.DisconnectAsync(circuitHost, circuitHost.Client.ConnectionId); tcs.SetResult(0); return(task); }); var connect = Task.Run(async() => { registry.BeforeDisconnect.Set(); await tcs.Task; await registry.ConnectAsync(circuitHost.CircuitId, client, newId, default); }); await Task.WhenAll(disconnect, connect); // Assert Assert.Single(registry.ConnectedCircuits.Values); Assert.False(registry.DisconnectedCircuits.TryGetValue(circuitHost.CircuitId, out _)); Assert.True(circuitHandler.OnConnectionDownExecuted, "OnConnectionDownAsync should have been executed."); Assert.True(circuitHandler.OnConnectionUpExecuted, "OnConnectionUpAsync should have been executed."); }