@Test
public void twoParts() throws IOException {

  when(upload.start()).thenReturn(UPLOAD_ID);
  ArgumentCaptor<S3Part> partCaptor = ArgumentCaptor.forClass(S3Part.class);
  when(upload.upload(eq(UPLOAD_ID), partCaptor.capture())).thenReturn(partETag1, partETag2);
  try (OutputStream output = new S3MultipartOutputStream(upload, 1, retry, asyncHandler)) {
    output.write(new byte[] { 0, 1 });
  }
  List<S3Part> parts = partCaptor.getAllValues();
  assertThat(parts.size(), is(2));
  Map<Integer, S3Part> map = Maps.uniqueIndex(parts, S3Part::getNumber);
  S3Part part1 = map.get(1);
  assertThat(part1.getNumber(), is(1));
  assertThat(part1.getSize(), is(1));
  assertThat(part1.getMd5(), is(MD5_FOR_BYTE_ZERO));
  assertThat(ByteStreams.toByteArray(part1.getInputStream()), is(new byte[] { 0 }));
  S3Part part2 = map.get(2);
  assertThat(part2.getNumber(), is(2));
  assertThat(part2.getSize(), is(1));
  assertThat(part2.getMd5(), is(MD5_FOR_BYTE_ONE));
  assertThat(ByteStreams.toByteArray(part2.getInputStream()), is(new byte[] { 1 }));
  @SuppressWarnings("unchecked")
  ArgumentCaptor<List<PartETag>> tagCaptor = ArgumentCaptor.forClass(List.class);
  verify(upload).complete(eq(UPLOAD_ID), tagCaptor.capture());
  assertThat(tagCaptor.getValue(), hasSize(2));
  assertThat(tagCaptor.getValue(), containsInAnyOrder(partETag1, partETag2));
}