@Test
  public void readAtLeastUsingSmallAppBuffer() throws Exception {
    final int amountToRead = 150;
    final int individualRead = 60;
    final int preexistingBytes = 10;
    ByteBuffer wrappedBuffer = ByteBuffer.allocate(1000);
    SocketChannel mockChannel = mock(SocketChannel.class);

    // force buffer expansion by making a small decoded buffer appear near to being full
    int initialUnwrappedBufferSize = 100;
    ByteBuffer unwrappedBuffer = ByteBuffer.allocate(initialUnwrappedBufferSize);
    unwrappedBuffer.position(7).limit(preexistingBytes + 7); // 7 bytes of message header - ignored

    nioSslEngine.getInputBufferVendorForTestingOnly().setBufferForTestingOnly(unwrappedBuffer);

    // simulate some socket reads
    when(mockChannel.read(any(ByteBuffer.class))).thenAnswer((Answer<Integer>) invocation -> {
      ByteBuffer buffer = invocation.getArgument(0);
      buffer.position(buffer.position() + individualRead);
      return individualRead;
    });

    TestSSLEngine testSSLEngine = new TestSSLEngine();
    testSSLEngine.addReturnResult(
        new SSLEngineResult(BUFFER_OVERFLOW, NEED_UNWRAP, 0, 0), // expand 100 bytes to 93*2+7
        new SSLEngineResult(OK, NEED_UNWRAP, 0, 0), // 10 + 60 bytes = 70
        new SSLEngineResult(OK, NEED_UNWRAP, 0, 0), // 70 + 60 bytes = 130
        new SSLEngineResult(OK, NEED_UNWRAP, 0, 0)); // 130 + 60 bytes = 190
    nioSslEngine.engine = testSSLEngine;

    try (final ByteBufferSharing sharedBuffer =
        nioSslEngine.readAtLeast(mockChannel, amountToRead, wrappedBuffer)) {
      ByteBuffer data = sharedBuffer.getBuffer();
      verify(mockChannel, times(3)).read(isA(ByteBuffer.class));
      assertThat(data.position()).isEqualTo(0);
      assertThat(data.limit()).isEqualTo(individualRead * 3 + preexistingBytes);
      // The initial available space in the unwrapped buffer should have doubled
      int initialFreeSpace = initialUnwrappedBufferSize - preexistingBytes;
      try (final ByteBufferSharing inputSharing =
          nioSslEngine.getInputBufferVendorForTestingOnly().open()) {
        assertThat(inputSharing.getBuffer().capacity())
            .isEqualTo(2 * initialFreeSpace + preexistingBytes);
      }
    }
  }
This tests the case where a message header has been read and part of a message has been read,
but the decoded buffer is too small to hold all of the message. In this case the readAtLeast
method will have to expand the capacity of the decoded buffer and return the new, expanded,
buffer as the method result.
geode-core/src/test/java/org/apache/geode/internal/net/NioSslEngineTest.java