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));
        }
Exemplo n.º 4
0
        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);
        }