@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();
    }
  }
Example #3
0
 public void stop() throws Exception {
   _stop = true;
   _channel.close().sync();
   workerGroup.shutdownGracefully();
   internalGroup.shutdownGracefully();
 }