public async Task TestReleaseAfterClosePool() { var addr = new LocalAddress(ChannelPoolTestUtils.GetLocalAddrId()); Bootstrap cb = new Bootstrap().RemoteAddress(addr).Group(_group).Channel<LocalChannel>(); ServerBootstrap sb = new ServerBootstrap() .Group(_group) .Channel<LocalServerChannel>() .ChildHandler( new ActionChannelInitializer<LocalChannel>( ch => ch.Pipeline.AddLast(new ChannelHandlerAdapter())) ); // Start server IChannel sc = await sb.BindAsync(addr); var pool = new FixedChannelPool(cb, new TestChannelPoolHandler(), 2); IChannel channel = await pool.AcquireAsync(); pool.Close(); await _group.GetNext().SubmitAsync(() => TaskUtil.Completed); var e = await Assert.ThrowsAsync<InvalidOperationException>(async () => await pool.ReleaseAsync(channel)); Assert.Same(FixedChannelPool.PoolClosedOnReleaseException, e); // Since the pool is closed, the Channel should have been closed as well. await channel.CloseCompletion; Assert.False(channel.IsOpen, "Unexpected open channel"); await sc.CloseAsync(); pool.Close(); }
private async Task TestAcquireTimeout0(long timeoutMillis) { var addr = new LocalAddress(ChannelPoolTestUtils.GetLocalAddrId()); Bootstrap cb = new Bootstrap().RemoteAddress(addr).Group(_group).Channel<LocalChannel>(); ServerBootstrap sb = new ServerBootstrap() .Group(_group) .Channel<LocalServerChannel>() .ChildHandler( new ActionChannelInitializer<LocalChannel>( ch => ch.Pipeline.AddLast(new ChannelHandlerAdapter())) ); // Start server IChannel sc = await sb.BindAsync(addr); var handler = new TestChannelPoolHandler(); var pool = new FixedChannelPool(cb, handler, ChannelActiveHealthChecker.Instance, FixedChannelPool.AcquireTimeoutAction.Fail, TimeSpan.FromMilliseconds(timeoutMillis), 1, int.MaxValue); IChannel channel = await pool.AcquireAsync(); try { await Assert.ThrowsAsync<TimeoutException>(async () => await pool.AcquireAsync()); } finally { await sc.CloseAsync(); await channel.CloseAsync(); pool.Close(); } }
public async Task TestReleaseDifferentPool() { var addr = new LocalAddress(ChannelPoolTestUtils.GetLocalAddrId()); Bootstrap cb = new Bootstrap().RemoteAddress(addr).Group(_group).Channel<LocalChannel>(); ServerBootstrap sb = new ServerBootstrap() .Group(_group) .Channel<LocalServerChannel>() .ChildHandler( new ActionChannelInitializer<LocalChannel>( ch => ch.Pipeline.AddLast(new ChannelHandlerAdapter())) ); // Start server IChannel sc = await sb.BindAsync(addr); var handler = new TestChannelPoolHandler(); var pool = new FixedChannelPool(cb, handler, 1, 1); var pool2 = new FixedChannelPool(cb, handler, 1, 1); IChannel channel = await pool.AcquireAsync(); try { await Assert.ThrowsAsync<ArgumentException>(async () => await pool2.ReleaseAsync(channel)); } finally { await sc.CloseAsync(); await channel.CloseAsync(); pool.Close(); pool2.Close(); } }
public async Task TestAcquireBoundQueue() { var addr = new LocalAddress(ChannelPoolTestUtils.GetLocalAddrId()); Bootstrap cb = new Bootstrap().RemoteAddress(addr).Group(_group).Channel<LocalChannel>(); ServerBootstrap sb = new ServerBootstrap() .Group(_group) .Channel<LocalServerChannel>() .ChildHandler( new ActionChannelInitializer<LocalChannel>( ch => ch.Pipeline.AddLast(new ChannelHandlerAdapter())) ); // Start server IChannel sc = await sb.BindAsync(addr); var handler = new TestChannelPoolHandler(); var pool = new FixedChannelPool(cb, handler, 1, 1); IChannel channel = await pool.AcquireAsync(); var future = pool.AcquireAsync(); Assert.False(future.IsCompleted); try { await Assert.ThrowsAsync<InvalidOperationException>(async () => await pool.AcquireAsync()); } finally { await sc.CloseAsync(); await channel.CloseAsync(); pool.Close(); } }
public async Task TestAcquireNewConnectionWhen() { var addr = new LocalAddress(ChannelPoolTestUtils.GetLocalAddrId()); Bootstrap cb = new Bootstrap().RemoteAddress(addr).Group(_group).Channel<LocalChannel>(); ServerBootstrap sb = new ServerBootstrap() .Group(_group) .Channel<LocalServerChannel>() .ChildHandler( new ActionChannelInitializer<LocalChannel>( ch => ch.Pipeline.AddLast(new ChannelHandlerAdapter())) ); // Start server IChannel sc = await sb.BindAsync(addr); var handler = new TestChannelPoolHandler(); var pool = new FixedChannelPool(cb, handler, 1); IChannel channel1 = await pool.AcquireAsync(); await channel1.CloseAsync(); #pragma warning disable CS4014 // 由于此调用不会等待,因此在调用完成前将继续执行当前方法 pool.ReleaseAsync(channel1); #pragma warning restore CS4014 // 由于此调用不会等待,因此在调用完成前将继续执行当前方法 IChannel channel2 = await pool.AcquireAsync(); Assert.NotSame(channel1, channel2); await sc.CloseAsync(); await channel2.CloseAsync(); pool.Close(); }
public async Task TestAcquireNewConnection() { var addr = new LocalAddress(ChannelPoolTestUtils.GetLocalAddrId()); Bootstrap cb = new Bootstrap().RemoteAddress(addr).Group(_group).Channel<LocalChannel>(); ServerBootstrap sb = new ServerBootstrap() .Group(_group) .Channel<LocalServerChannel>() .ChildHandler( new ActionChannelInitializer<LocalChannel>( ch => ch.Pipeline.AddLast(new ChannelHandlerAdapter())) ); // Start server IChannel sc = await sb.BindAsync(addr); var handler = new TestChannelPoolHandler(); var pool = new FixedChannelPool( cb, handler, ChannelActiveHealthChecker.Instance, FixedChannelPool.AcquireTimeoutAction.New, TimeSpan.FromMilliseconds(500), 1, int.MaxValue); IChannel channel = await pool.AcquireAsync(); IChannel channel2 = await pool.AcquireAsync(); Assert.NotSame(channel, channel2); await sc.CloseAsync(); await channel.CloseAsync(); await channel2.CloseAsync(); pool.Close(); }
public async Task TestReleaseClosed() { var addr = new LocalAddress(ChannelPoolTestUtils.GetLocalAddrId()); Bootstrap cb = new Bootstrap().RemoteAddress(addr).Group(_group).Channel <LocalChannel>(); ServerBootstrap sb = new ServerBootstrap() .Group(_group) .Channel <LocalServerChannel>() .ChildHandler( new ActionChannelInitializer <LocalChannel>( ch => ch.Pipeline.AddLast(new ChannelHandlerAdapter())) ); // Start server IChannel sc = await sb.BindAsync(addr); var pool = new FixedChannelPool(cb, new TestChannelPoolHandler(), 2); IChannel channel = await pool.AcquireAsync(); await channel.CloseAsync(); await pool.ReleaseAsync(channel); await sc.CloseAsync(); pool.Close(); }
public async Task TestAcquire() { var addr = new LocalAddress(ChannelPoolTestUtils.GetLocalAddrId()); Bootstrap cb = new Bootstrap().RemoteAddress(addr).Group(_group).Channel <LocalChannel>(); ServerBootstrap sb = new ServerBootstrap() .Group(_group) .Channel <LocalServerChannel>() .ChildHandler( new ActionChannelInitializer <LocalChannel>( ch => ch.Pipeline.AddLast(new ChannelHandlerAdapter())) ); // Start server IChannel sc = await sb.BindAsync(addr); var handler = new CountingChannelPoolHandler(); var pool = new FixedChannelPool(cb, handler, 1); IChannel channel = await pool.AcquireAsync(); var future = pool.AcquireAsync(); Assert.False(future.IsCompleted); await pool.ReleaseAsync(channel); await Task.Delay(TimeSpan.FromSeconds(1)); Assert.True(future.IsCompleted); IChannel channel2 = future.Result; Assert.Same(channel, channel2); Assert.Equal(1, handler.ChannelCount); Assert.Equal(1, handler.AcquiredCount); Assert.Equal(1, handler.ReleasedCount); await sc.CloseAsync(); await channel2.CloseAsync(); pool.Close(); }
public async Task TestDeadlockOnRemove() { IEventLoop thread1 = new SingleThreadEventLoop(); Bootstrap bootstrap1 = new Bootstrap() .Channel <LocalChannel>().Group(thread1).LocalAddress(new LocalAddress("#1")); IEventLoop thread2 = new SingleThreadEventLoop(); Bootstrap bootstrap2 = new Bootstrap() .Channel <LocalChannel>().Group(thread2).LocalAddress(new LocalAddress("#2")); // pool1 runs on thread2, pool2 runs on thread1 FixedChannelPool pool1 = new FixedChannelPool(bootstrap2, NoopHandler.Instance, 1); FixedChannelPool pool2 = new FixedChannelPool(bootstrap1, NoopHandler.Instance, 1); var channelPoolMap = new TestChannelPoolMap1(pool1, pool2); Assert.Same(pool1, channelPoolMap.Get("#1")); Assert.Same(pool2, channelPoolMap.Get("#2")); // thread1 tries to remove pool1 which is running on thread2 // thread2 tries to remove pool2 which is running on thread1 var barrier = new Barrier(2); var future1 = thread1.SubmitAsync(() => { if (!barrier.SignalAndWait(TimeSpan.FromSeconds(1))) { throw new TimeoutException(); } channelPoolMap.Remove("#1"); return(1); }); var future2 = thread2.SubmitAsync(() => { if (!barrier.SignalAndWait(TimeSpan.FromSeconds(1))) { throw new TimeoutException(); } channelPoolMap.Remove("#2"); return(2); }); // A blocking close on remove will cause a deadlock here and the test will time out try { var result = await TaskUtil.WaitAsync(future1, TimeSpan.FromSeconds(1)); if (!result || !future1.IsSuccess()) { throw new TimeoutException(); } result = await TaskUtil.WaitAsync(future2, TimeSpan.FromSeconds(1)); if (!result || !future2.IsSuccess()) { throw new TimeoutException(); } } catch (TimeoutException) { Assert.False(true); // Fail the test on timeout to distinguish from other errors } finally { pool1.Close(); pool2.Close(); channelPoolMap.Close(); Shutdown(thread1, thread2); } }
public async Task TestDeadlockOnAcquire() { IEventLoop threadA1 = new SingleThreadEventLoop(); Bootstrap bootstrapA1 = new Bootstrap() .Channel <LocalChannel>().Group(threadA1).LocalAddress(new LocalAddress("A1")); IEventLoop threadA2 = new SingleThreadEventLoop(); Bootstrap bootstrapA2 = new Bootstrap() .Channel <LocalChannel>().Group(threadA2).LocalAddress(new LocalAddress("A2")); IEventLoop threadB1 = new SingleThreadEventLoop(); Bootstrap bootstrapB1 = new Bootstrap() .Channel <LocalChannel>().Group(threadB1).LocalAddress(new LocalAddress("B1")); IEventLoop threadB2 = new SingleThreadEventLoop(); Bootstrap bootstrapB2 = new Bootstrap() .Channel <LocalChannel>().Group(threadB2).LocalAddress(new LocalAddress("B2")); FixedChannelPool poolA1 = new FixedChannelPool(bootstrapA1, NoopHandler.Instance, 1); FixedChannelPool poolA2 = new FixedChannelPool(bootstrapB2, NoopHandler.Instance, 1); FixedChannelPool poolB1 = new FixedChannelPool(bootstrapB1, NoopHandler.Instance, 1); FixedChannelPool poolB2 = new FixedChannelPool(bootstrapA2, NoopHandler.Instance, 1); // Synchronize threads on these barriers to ensure order of execution, first wait until each thread is inside // the newPool callbak, then hold the two threads that should lose the match until the first two returns, then // release them to test if they deadlock when trying to release their pools on each other's threads. Barrier arrivalBarrier = new Barrier(4); Barrier releaseBarrier = new Barrier(3); var channelPoolMap = new TestChannelPoolMap0( threadA1, threadA2, threadB1, threadB2, poolA1, poolA2, poolB1, poolB2, arrivalBarrier, releaseBarrier); // Thread A1 calls ChannelPoolMap.get(A) // Thread A2 calls ChannelPoolMap.get(A) // Thread B1 calls ChannelPoolMap.get(B) // Thread B2 calls ChannelPoolMap.get(B) var futureA1 = threadA1.SubmitAsync(() => { return(channelPoolMap.Get("A")); }); var futureA2 = threadA2.SubmitAsync(() => { return(channelPoolMap.Get("A")); }); var futureB1 = threadB1.SubmitAsync(() => { return(channelPoolMap.Get("B")); }); var futureB2 = threadB2.SubmitAsync(() => { return(channelPoolMap.Get("B")); }); // Thread A1 succeeds on updating the map and moves on // Thread B1 succeeds on updating the map and moves on // These should always succeed and return with new pools try { var result = await TaskUtil.WaitAsync(futureA1, TimeSpan.FromSeconds(1)); if (!result || !futureA1.IsSuccess()) { throw new TimeoutException(); } Assert.Same(poolA1, futureA1.Result); result = await TaskUtil.WaitAsync(futureB1, TimeSpan.FromSeconds(1)); if (!result || !futureB1.IsSuccess()) { throw new TimeoutException(); } Assert.Same(poolB1, futureB1.Result); } catch (Exception e) { Shutdown(threadA1, threadA2, threadB1, threadB2); throw e; } // Now release the other two threads which at this point lost the race and will try to clean up the acquired // pools. The expected scenario is that both pools close, in case of a deadlock they will hang. if (!releaseBarrier.SignalAndWait(TimeSpan.FromSeconds(1))) { Assert.False(true); } // Thread A2 fails to update the map and submits close to thread B2 // Thread B2 fails to update the map and submits close to thread A2 // If the close is blocking, then these calls will time out as the threads are waiting for each other // If the close is not blocking, then the previously created pools will be returned try { var result = await TaskUtil.WaitAsync(futureA2, TimeSpan.FromSeconds(1)); if (!result || !futureA2.IsSuccess()) { throw new TimeoutException(); } Assert.Same(poolA1, futureA2.Result); result = await TaskUtil.WaitAsync(futureB2, TimeSpan.FromSeconds(1)); if (!result || !futureB2.IsSuccess()) { throw new TimeoutException(); } Assert.Same(poolB1, futureB2.Result); } catch (TimeoutException) { Assert.False(true); // Fail the test on timeout to distinguish from other errors throw; } finally { poolA1.Close(); poolA2.Close(); poolB1.Close(); poolB2.Close(); channelPoolMap.Close(); Shutdown(threadA1, threadA2, threadB1, threadB2); } }