public async Task EnsureCreate_Can_Handle_Multiple_Concurrent_Calls() { var mock = GetPoolMock(null, GetConfig(3, 3)); var creationCounter = 0; var isCreating = 0; mock.Setup(p => p.DoCreateAndOpen()).Returns(() => { Interlocked.Increment(ref creationCounter); Interlocked.Exchange(ref isCreating, 1); return(TestHelper.DelayedTask(CreateConnection(), 50, () => Interlocked.Exchange(ref isCreating, 0))); }); var pool = mock.Object; pool.SetDistance(HostDistance.Local); Assert.AreEqual(0, pool.OpenConnections); var tasks = new Task[100]; for (var i = 0; i < 100; i++) { tasks[i] = Task.Run(async() => await pool.EnsureCreate()); } await Task.WhenAll(tasks); Assert.Greater(pool.OpenConnections, 0); Assert.LessOrEqual(pool.OpenConnections, 3); await TestHelper.WaitUntilAsync(() => Volatile.Read(ref creationCounter) == 3, 200, 20); Assert.AreEqual(3, Volatile.Read(ref creationCounter)); Assert.AreEqual(0, Volatile.Read(ref isCreating)); Assert.AreEqual(3, pool.OpenConnections); }
public async Task OnHostUp_Recreates_Pool_In_The_Background() { var mock = GetPoolMock(null, GetConfig(2, 2)); var creationCounter = 0; var isCreating = 0; mock.Setup(p => p.DoCreateAndOpen()).Returns(() => { Interlocked.Increment(ref creationCounter); Interlocked.Exchange(ref isCreating, 1); return(TestHelper.DelayedTask(CreateConnection(), 30, () => Interlocked.Exchange(ref isCreating, 0))); }); var pool = mock.Object; pool.SetDistance(HostDistance.Local); Assert.AreEqual(0, pool.OpenConnections); Assert.AreEqual(0, Volatile.Read(ref creationCounter)); Assert.AreEqual(0, Volatile.Read(ref isCreating)); pool.OnHostUp(null); await TestHelper.WaitUntilAsync(() => pool.OpenConnections == 2); Assert.AreEqual(2, pool.OpenConnections); Assert.AreEqual(2, Volatile.Read(ref creationCounter)); Assert.AreEqual(0, Volatile.Read(ref isCreating)); }
public async Task EnsureCreate_After_Reconnection_Attempt_Waits_Existing() { var mock = GetPoolMock(null, GetConfig(2, 2)); var creationCounter = 0; var isCreating = 0; mock.Setup(p => p.DoCreateAndOpen()).Returns(() => { Interlocked.Increment(ref creationCounter); Interlocked.Exchange(ref isCreating, 1); return(TestHelper.DelayedTask(CreateConnection(), 300, () => Interlocked.Exchange(ref isCreating, 0))); }); var pool = mock.Object; pool.SetDistance(HostDistance.Local); Assert.AreEqual(0, pool.OpenConnections); Thread.Sleep(100); pool.OnHostUp(null); await pool.EnsureCreate(); Assert.AreEqual(1, pool.OpenConnections); await TestHelper.WaitUntilAsync(() => pool.OpenConnections == 2, 200, 30); Assert.AreEqual(2, Volatile.Read(ref creationCounter)); Assert.AreEqual(2, pool.OpenConnections); Assert.AreEqual(0, Volatile.Read(ref isCreating)); }
public async Task ReadParse_While_Disposing_Faults_Tasks_But_Never_Throws() { var connectionMock = GetConnectionMock(); var responses = new ConcurrentBag <object>(); connectionMock.Setup(c => c.RemoveFromPending(It.IsAny <short>())) .Returns(() => new OperationState((ex, r) => responses.Add((object)ex ?? r))); var connection = connectionMock.Object; var bufferBuilder = Enumerable.Empty <byte>(); const int totalFrames = 63; for (var i = 0; i < totalFrames; i++) { bufferBuilder = bufferBuilder.Concat(GetResultBuffer((byte)i)); } var buffer = bufferBuilder.ToArray(); var schedulerPair = new ConcurrentExclusiveSchedulerPair(); var tasks = new List <Task>(buffer.Length); for (var i = 0; i < buffer.Length; i++) { var index = i; tasks.Add( Task.Factory.StartNew(() => connection.ReadParse(buffer.Skip(index).ToArray(), 1), CancellationToken.None, TaskCreationOptions.None, schedulerPair.ExclusiveScheduler)); } var random = new Random(); // Lets wait for some of the read tasks to be completed await tasks[random.Next(20, 50)].ConfigureAwait(false); await Task.Run(() => connection.Dispose()).ConfigureAwait(false); await Task.WhenAll(tasks).ConfigureAwait(false); // We must await for a short while until operation states are callback (on the TaskScheduler) await TestHelper.WaitUntilAsync(() => totalFrames == responses.Count, 100, 30); Assert.AreEqual(totalFrames, responses.Count); }