/**
   * Executes the deserialization method.
   *
   * @param rbc the byte channel to read the serialized data from
   * @param bpb the buffer provider broker to request empty buffers from
   * @return the deserialized transfer envelope
   * @throws IOException thrown if an error occurs during the deserialization process
   * @throws NoBufferAvailableException thrown if the buffer provider broker could not provide an
   *     empty buffer
   */
  private TransferEnvelope executeDeserialization(
      final ReadableByteChannel rbc, final BufferProviderBroker bpb)
      throws IOException, NoBufferAvailableException {

    final DefaultDeserializer dd = new DefaultDeserializer(bpb);

    TransferEnvelope te = dd.getFullyDeserializedTransferEnvelope();
    while (te == null) {

      dd.read(rbc);
      te = dd.getFullyDeserializedTransferEnvelope();
    }

    assertEquals(SEQUENCE_NUMBER, te.getSequenceNumber());
    assertEquals(JOB_ID, te.getJobID());
    assertEquals(CHANNEL_ID, te.getSource());

    return te;
  }
  /**
   * Tests the deserialization process of a {@link TransferEnvelope} without a buffer and without
   * interruptions of the byte stream.
   */
  @Test
  public void testDeserializationWithoutBufferAndInterruptions() {

    try {

      final ReadableByteChannel rbc = createByteChannel(null, -1);

      final TestBufferProviderBroker tbpb = new TestBufferProviderBroker(new TestBufferProvider(1));

      final TransferEnvelope te = executeDeserialization(rbc, tbpb);

      assertNull(te.getBuffer());

    } catch (IOException ioe) {
      fail(StringUtils.stringifyException(ioe));
    } catch (NoBufferAvailableException nbae) {
      fail(StringUtils.stringifyException(nbae));
    }
  }
  /**
   * Constructs an {@link InterruptibleByteChannel} from which the deserializer to be tested can
   * read its data.
   *
   * @param readInterruptPositions the positions after which the byte stream shall be interrupted
   * @param testBufferSize the size of the test buffer to create
   * @return an {@link InterruptibleByteChannel} holding the serialized data in memory
   * @throws IOException thrown if an error occurs while serializing the original data
   */
  private ReadableByteChannel createByteChannel(
      final int[] readInterruptPositions, final int testBufferSize) throws IOException {

    final TransferEnvelope te = new TransferEnvelope(SEQUENCE_NUMBER, JOB_ID, CHANNEL_ID);

    if (testBufferSize >= 0) {

      if (testBufferSize > 100) {
        throw new IllegalStateException("Test buffer size can be 100 bytes at most");
      }

      final Queue<MemorySegment> bufferPool = new ArrayDeque<MemorySegment>();
      final MemorySegment ms = new MemorySegment(new byte[TEST_BUFFER_CAPACITY]);

      final MemoryBuffer buffer =
          BufferFactory.createFromMemory(ms.size(), ms, new BufferPoolConnector(bufferPool));

      final ByteBuffer srcBuffer = ByteBuffer.allocate(testBufferSize);
      for (int i = 0; i < testBufferSize; ++i) {
        srcBuffer.put((byte) i);
      }
      srcBuffer.flip();

      buffer.write(srcBuffer);
      buffer.flip();
      te.setBuffer(buffer);
    }

    final DefaultSerializer ds = new DefaultSerializer();
    ds.setTransferEnvelope(te);

    final InterruptibleByteChannel ibc = new InterruptibleByteChannel(null, readInterruptPositions);

    while (ds.write(ibc)) ;

    ibc.switchToReadPhase();

    return ibc;
  }