@Test(timeout = 30000) @Ignore public void testConcurrentMessageBufferAccess() throws Throwable { EventLoopGroup l = new LocalEventLoopGroup(4, new DefaultThreadFactory("l")); EventExecutorGroup e1 = new DefaultEventExecutorGroup(4, new DefaultThreadFactory("e1")); EventExecutorGroup e2 = new DefaultEventExecutorGroup(4, new DefaultThreadFactory("e2")); EventExecutorGroup e3 = new DefaultEventExecutorGroup(4, new DefaultThreadFactory("e3")); EventExecutorGroup e4 = new DefaultEventExecutorGroup(4, new DefaultThreadFactory("e4")); EventExecutorGroup e5 = new DefaultEventExecutorGroup(4, new DefaultThreadFactory("e5")); try { final MessageForwarder1 h1 = new MessageForwarder1(); final MessageForwarder2 h2 = new MessageForwarder2(); final MessageForwarder3 h3 = new MessageForwarder3(); final MessageForwarder1 h4 = new MessageForwarder1(); final MessageForwarder2 h5 = new MessageForwarder2(); final MessageDiscarder h6 = new MessageDiscarder(); final Channel ch = new LocalChannel(); // inbound: int -> byte[4] -> int -> int -> byte[4] -> int -> /dev/null // outbound: int -> int -> byte[4] -> int -> int -> byte[4] -> /dev/null ch.pipeline() .addLast(h1) .addLast(e1, h2) .addLast(e2, h3) .addLast(e3, h4) .addLast(e4, h5) .addLast(e5, h6); l.register(ch).sync().channel().connect(localAddr).sync(); final int ROUNDS = 1024; final int ELEMS_PER_ROUNDS = 8192; final int TOTAL_CNT = ROUNDS * ELEMS_PER_ROUNDS; for (int i = 0; i < TOTAL_CNT; ) { final int start = i; final int end = i + ELEMS_PER_ROUNDS; i = end; ch.eventLoop() .execute( new Runnable() { @Override public void run() { for (int j = start; j < end; j++) { ch.pipeline().fireChannelRead(Integer.valueOf(j)); } } }); } while (h1.inCnt < TOTAL_CNT || h2.inCnt < TOTAL_CNT || h3.inCnt < TOTAL_CNT || h4.inCnt < TOTAL_CNT || h5.inCnt < TOTAL_CNT || h6.inCnt < TOTAL_CNT) { if (h1.exception.get() != null) { throw h1.exception.get(); } if (h2.exception.get() != null) { throw h2.exception.get(); } if (h3.exception.get() != null) { throw h3.exception.get(); } if (h4.exception.get() != null) { throw h4.exception.get(); } if (h5.exception.get() != null) { throw h5.exception.get(); } if (h6.exception.get() != null) { throw h6.exception.get(); } Thread.sleep(10); } for (int i = 0; i < TOTAL_CNT; ) { final int start = i; final int end = i + ELEMS_PER_ROUNDS; i = end; ch.pipeline() .context(h6) .executor() .execute( new Runnable() { @Override public void run() { for (int j = start; j < end; j++) { ch.write(Integer.valueOf(j)); } ch.flush(); } }); } while (h1.outCnt < TOTAL_CNT || h2.outCnt < TOTAL_CNT || h3.outCnt < TOTAL_CNT || h4.outCnt < TOTAL_CNT || h5.outCnt < TOTAL_CNT || h6.outCnt < TOTAL_CNT) { if (h1.exception.get() != null) { throw h1.exception.get(); } if (h2.exception.get() != null) { throw h2.exception.get(); } if (h3.exception.get() != null) { throw h3.exception.get(); } if (h4.exception.get() != null) { throw h4.exception.get(); } if (h5.exception.get() != null) { throw h5.exception.get(); } if (h6.exception.get() != null) { throw h6.exception.get(); } Thread.sleep(10); } ch.close().sync(); } finally { l.shutdownGracefully(); e1.shutdownGracefully(); e2.shutdownGracefully(); e3.shutdownGracefully(); e4.shutdownGracefully(); e5.shutdownGracefully(); l.terminationFuture().sync(); e1.terminationFuture().sync(); e2.terminationFuture().sync(); e3.terminationFuture().sync(); e4.terminationFuture().sync(); e5.terminationFuture().sync(); } }
@Test(timeout = 5000) public void testStagedExecution() throws Throwable { EventLoopGroup l = new LocalEventLoopGroup(4, new DefaultThreadFactory("l")); EventExecutorGroup e1 = new DefaultEventExecutorGroup(4, new DefaultThreadFactory("e1")); EventExecutorGroup e2 = new DefaultEventExecutorGroup(4, new DefaultThreadFactory("e2")); ThreadNameAuditor h1 = new ThreadNameAuditor(); ThreadNameAuditor h2 = new ThreadNameAuditor(); ThreadNameAuditor h3 = new ThreadNameAuditor(); Channel ch = new LocalChannel(); // With no EventExecutor specified, h1 will be always invoked by EventLoop 'l'. ch.pipeline().addLast(h1); // h2 will be always invoked by EventExecutor 'e1'. ch.pipeline().addLast(e1, h2); // h3 will be always invoked by EventExecutor 'e2'. ch.pipeline().addLast(e2, h3); l.register(ch).sync().channel().connect(localAddr).sync(); // Fire inbound events from all possible starting points. ch.pipeline().fireChannelRead("1"); ch.pipeline().context(h1).fireChannelRead("2"); ch.pipeline().context(h2).fireChannelRead("3"); ch.pipeline().context(h3).fireChannelRead("4"); // Fire outbound events from all possible starting points. ch.pipeline().write("5"); ch.pipeline().context(h3).write("6"); ch.pipeline().context(h2).write("7"); ch.pipeline().context(h1).write("8").flush().sync(); ch.close().sync(); // Wait until all events are handled completely. while (h1.outboundThreadNames.size() < 3 || h3.inboundThreadNames.size() < 3 || h1.removalThreadNames.size() < 1) { if (h1.exception.get() != null) { throw h1.exception.get(); } if (h2.exception.get() != null) { throw h2.exception.get(); } if (h3.exception.get() != null) { throw h3.exception.get(); } Thread.sleep(10); } String currentName = Thread.currentThread().getName(); try { // Events should never be handled from the current thread. Assert.assertFalse(h1.inboundThreadNames.contains(currentName)); Assert.assertFalse(h2.inboundThreadNames.contains(currentName)); Assert.assertFalse(h3.inboundThreadNames.contains(currentName)); Assert.assertFalse(h1.outboundThreadNames.contains(currentName)); Assert.assertFalse(h2.outboundThreadNames.contains(currentName)); Assert.assertFalse(h3.outboundThreadNames.contains(currentName)); Assert.assertFalse(h1.removalThreadNames.contains(currentName)); Assert.assertFalse(h2.removalThreadNames.contains(currentName)); Assert.assertFalse(h3.removalThreadNames.contains(currentName)); // Assert that events were handled by the correct executor. for (String name : h1.inboundThreadNames) { Assert.assertTrue(name.startsWith("l-")); } for (String name : h2.inboundThreadNames) { Assert.assertTrue(name.startsWith("e1-")); } for (String name : h3.inboundThreadNames) { Assert.assertTrue(name.startsWith("e2-")); } for (String name : h1.outboundThreadNames) { Assert.assertTrue(name.startsWith("l-")); } for (String name : h2.outboundThreadNames) { Assert.assertTrue(name.startsWith("e1-")); } for (String name : h3.outboundThreadNames) { Assert.assertTrue(name.startsWith("e2-")); } for (String name : h1.removalThreadNames) { Assert.assertTrue(name.startsWith("l-")); } for (String name : h2.removalThreadNames) { Assert.assertTrue(name.startsWith("e1-")); } for (String name : h3.removalThreadNames) { Assert.assertTrue(name.startsWith("e2-")); } // Assert that the events for the same handler were handled by the same thread. Set<String> names = new HashSet<String>(); names.addAll(h1.inboundThreadNames); names.addAll(h1.outboundThreadNames); names.addAll(h1.removalThreadNames); Assert.assertEquals(1, names.size()); names.clear(); names.addAll(h2.inboundThreadNames); names.addAll(h2.outboundThreadNames); names.addAll(h2.removalThreadNames); Assert.assertEquals(1, names.size()); names.clear(); names.addAll(h3.inboundThreadNames); names.addAll(h3.outboundThreadNames); names.addAll(h3.removalThreadNames); Assert.assertEquals(1, names.size()); // Count the number of events Assert.assertEquals(1, h1.inboundThreadNames.size()); Assert.assertEquals(2, h2.inboundThreadNames.size()); Assert.assertEquals(3, h3.inboundThreadNames.size()); Assert.assertEquals(3, h1.outboundThreadNames.size()); Assert.assertEquals(2, h2.outboundThreadNames.size()); Assert.assertEquals(1, h3.outboundThreadNames.size()); Assert.assertEquals(1, h1.removalThreadNames.size()); Assert.assertEquals(1, h2.removalThreadNames.size()); Assert.assertEquals(1, h3.removalThreadNames.size()); } catch (AssertionError e) { System.out.println("H1I: " + h1.inboundThreadNames); System.out.println("H2I: " + h2.inboundThreadNames); System.out.println("H3I: " + h3.inboundThreadNames); System.out.println("H1O: " + h1.outboundThreadNames); System.out.println("H2O: " + h2.outboundThreadNames); System.out.println("H3O: " + h3.outboundThreadNames); System.out.println("H1R: " + h1.removalThreadNames); System.out.println("H2R: " + h2.removalThreadNames); System.out.println("H3R: " + h3.removalThreadNames); throw e; } finally { l.shutdownGracefully(); e1.shutdownGracefully(); e2.shutdownGracefully(); l.terminationFuture().sync(); e1.terminationFuture().sync(); e2.terminationFuture().sync(); } }
public void stop() throws Exception { _stop = true; _channel.close().sync(); workerGroup.shutdownGracefully(); internalGroup.shutdownGracefully(); }