@Test
	public void testReadingCallable() throws Exception {

		// Exit gracefully on close

		Pipe pipe = Pipe.open();

		final SourceChannel sourceChannel = pipe.source();
		SinkChannel sinkChannel = pipe.sink();

		try {
			MockRegistrationReference mockRegistrationReference =
				new MockRegistrationReference(_executorIntraband);

			ChannelContext channelContext = new ChannelContext(
				new LinkedList<Datagram>());

			channelContext.setRegistrationReference(mockRegistrationReference);

			ReadingCallable readingCallable =
				_executorIntraband.new ReadingCallable(
					sourceChannel, channelContext);

			SyncThrowableThread<Void> syncThrowableThread =
				new SyncThrowableThread<>(
					new Callable<Void>() {

						@Override
						public Void call() throws Exception {
							sleep(100);

							sourceChannel.close();

							return null;
						}

					});

			syncThrowableThread.start();

			readingCallable.openLatch();

			Void result = readingCallable.call();

			syncThrowableThread.sync();

			Assert.assertNull(result);
			Assert.assertFalse(mockRegistrationReference.isValid());
		}
		finally {
			sourceChannel.close();
			sinkChannel.close();
		}
	}
  @Test
  public void testSendDatagramWithoutCallback() throws Exception {

    // Single datagram sending

    Pipe readPipe = Pipe.open();
    Pipe writePipe = Pipe.open();

    GatheringByteChannel gatheringByteChannel = writePipe.sink();
    ScatteringByteChannel scatteringByteChannel = readPipe.source();

    SelectionKeyRegistrationReference registrationReference =
        (SelectionKeyRegistrationReference)
            _selectorIntraband.registerChannel(writePipe.source(), readPipe.sink());

    Thread wakeUpThread = new Thread(new WakeUpRunnable(_selectorIntraband));

    wakeUpThread.start();

    Selector selector = _selectorIntraband.selector;

    synchronized (selector) {
      wakeUpThread.interrupt();
      wakeUpThread.join();

      Datagram requestDatagram = Datagram.createRequestDatagram(_type, _data);

      _selectorIntraband.sendDatagram(registrationReference, requestDatagram);

      SelectionKey writeSelectionKey = registrationReference.writeSelectionKey;

      ChannelContext channelContext = (ChannelContext) writeSelectionKey.attachment();

      Queue<Datagram> sendingQueue = channelContext.getSendingQueue();

      Assert.assertEquals(1, sendingQueue.size());
      Assert.assertSame(requestDatagram, sendingQueue.peek());
    }

    Datagram receiveDatagram = IntrabandTestUtil.readDatagramFully(scatteringByteChannel);

    Assert.assertEquals(_type, receiveDatagram.getType());

    ByteBuffer dataByteBuffer = receiveDatagram.getDataByteBuffer();

    Assert.assertArrayEquals(_data, dataByteBuffer.array());

    // Two datagrams continuous sending

    Datagram requestDatagram1 = Datagram.createRequestDatagram(_type, _data);
    Datagram requestDatagram2 = Datagram.createRequestDatagram(_type, _data);

    wakeUpThread = new Thread(new WakeUpRunnable(_selectorIntraband));

    wakeUpThread.start();

    synchronized (selector) {
      wakeUpThread.interrupt();
      wakeUpThread.join();

      _selectorIntraband.sendDatagram(registrationReference, requestDatagram1);
      _selectorIntraband.sendDatagram(registrationReference, requestDatagram2);

      SelectionKey writeSelectionKey = registrationReference.writeSelectionKey;

      ChannelContext channelContext = (ChannelContext) writeSelectionKey.attachment();

      Queue<Datagram> sendingQueue = channelContext.getSendingQueue();

      Assert.assertEquals(2, sendingQueue.size());

      Datagram[] datagrams = sendingQueue.toArray(new Datagram[2]);

      Assert.assertSame(requestDatagram1, datagrams[0]);
      Assert.assertSame(requestDatagram2, datagrams[1]);
    }

    Datagram receiveDatagram1 = IntrabandTestUtil.readDatagramFully(scatteringByteChannel);

    Assert.assertEquals(_type, receiveDatagram1.getType());

    dataByteBuffer = receiveDatagram1.getDataByteBuffer();

    Assert.assertArrayEquals(_data, dataByteBuffer.array());

    Datagram receiveDatagram2 = IntrabandTestUtil.readDatagramFully(scatteringByteChannel);

    Assert.assertEquals(_type, receiveDatagram2.getType());

    dataByteBuffer = receiveDatagram2.getDataByteBuffer();

    Assert.assertArrayEquals(_data, dataByteBuffer.array());

    // Two datagrams delay sending

    requestDatagram1 = Datagram.createRequestDatagram(_type, _data);
    requestDatagram2 = Datagram.createRequestDatagram(_type, _data);

    wakeUpThread = new Thread(new WakeUpRunnable(_selectorIntraband));

    wakeUpThread.start();

    SelectionKey writeSelectionKey = registrationReference.writeSelectionKey;

    ChannelContext channelContext = (ChannelContext) writeSelectionKey.attachment();

    Queue<Datagram> sendingQueue = channelContext.getSendingQueue();

    synchronized (writeSelectionKey) {
      synchronized (selector) {
        wakeUpThread.interrupt();
        wakeUpThread.join();

        _selectorIntraband.sendDatagram(registrationReference, requestDatagram1);

        Assert.assertEquals(1, sendingQueue.size());
        Assert.assertSame(requestDatagram1, sendingQueue.peek());
      }

      receiveDatagram1 = IntrabandTestUtil.readDatagramFully(scatteringByteChannel);

      Assert.assertEquals(_type, receiveDatagram1.getType());

      dataByteBuffer = receiveDatagram1.getDataByteBuffer();

      Assert.assertArrayEquals(_data, dataByteBuffer.array());

      Thread pollingThread = _selectorIntraband.pollingThread;

      while (pollingThread.getState() == Thread.State.RUNNABLE) ;

      _selectorIntraband.sendDatagram(registrationReference, requestDatagram2);

      Assert.assertEquals(1, sendingQueue.size());
      Assert.assertSame(requestDatagram2, sendingQueue.peek());
    }

    receiveDatagram2 = IntrabandTestUtil.readDatagramFully(scatteringByteChannel);

    Assert.assertEquals(_type, receiveDatagram2.getType());

    dataByteBuffer = receiveDatagram2.getDataByteBuffer();

    Assert.assertArrayEquals(_data, dataByteBuffer.array());

    // Huge datagram sending

    int hugeBufferSize = 1024 * 1024 * 10;

    ByteBuffer hugeBuffer = ByteBuffer.allocate(hugeBufferSize);

    for (int i = 0; i < hugeBufferSize; i++) {
      hugeBuffer.put(i, (byte) i);
    }

    _selectorIntraband.sendDatagram(
        registrationReference, Datagram.createRequestDatagram(_type, hugeBuffer));

    receiveDatagram = DatagramHelper.createReceiveDatagram();

    channelContext = (ChannelContext) writeSelectionKey.attachment();

    int count = 0;

    while (!DatagramHelper.readFrom(receiveDatagram, scatteringByteChannel)) {

      count++;
    }

    Assert.assertTrue(count > 0);

    sendingQueue = channelContext.getSendingQueue();

    Assert.assertTrue(sendingQueue.isEmpty());

    dataByteBuffer = receiveDatagram.getDataByteBuffer();

    Assert.assertArrayEquals(hugeBuffer.array(), dataByteBuffer.array());

    unregisterChannels(registrationReference);

    gatheringByteChannel.close();
    scatteringByteChannel.close();
  }