HttpClient { public void partialGet(URI uri, List<ContentRange> ranges, Map<String, ? extends Credentials> credentials, RangeReceiver receiver, RangeTransferListener listener) throws IOException, HttpError { final Set<ContentRange> remaining = new LinkedHashSet<>(ranges); while (!remaining.isEmpty()) { final List<ContentRange> next = copyOf(limit(remaining, min(remaining.size(), MAXIMUM_RANGES_PER_HTTP_REQUEST))); final HttpTransferListener requestListener = listener.newTransfer(next); final Response response = executeWithAuthRetry(uri, credentials, requestListener, next); final int code = response.code(); if (code == HTTP_OK) { receiver.receive(new ContentRange(0, response.body().contentLength()), inputStream(response, requestListener)); return; } if (code != HTTP_PARTIAL) { throw new HttpError(response.message(), code); } final MediaType mediaType = parseContentType(response); if (mediaType != null && "multipart".equals(mediaType.type())) { final byte[] boundary = getBoundary(mediaType); handleMultiPartBody(response, receiver, remaining, requestListener, boundary); } else { handleSinglePartBody(response, receiver, remaining, requestListener); } } } HttpClient(OkHttpClient okHttpClient); static HttpClient newHttpClient(); static HttpClient newHttpClient(OkHttpClient okHttpClient); void get(URI uri, Path output, Map<String, ? extends Credentials> credentials, HttpTransferListener listener); InputStream get(URI uri, Map<String, ? extends Credentials> credentials, HttpTransferListener listener); void partialGet(URI uri, List<ContentRange> ranges, Map<String, ? extends Credentials> credentials,
      RangeReceiver receiver, RangeTransferListener listener);  }
@SuppressWarnings("unchecked") @Test public void runtimeExceptionThrownForIoExceptionDuringHttpCommunication() throws Exception { OkHttpClient mockHttpClient = mock(OkHttpClient.class); RangeReceiver mockReceiver = mock(RangeReceiver.class); RangeTransferListener listener = mock(RangeTransferListener.class); when(listener.newTransfer(any(List.class))).thenReturn(mock(HttpTransferListener.class)); List<ContentRange> ranges = this.createSomeRanges(1); URI url = new URI("http: IOException expected = new IOException("IO"); Call mockCall = mock(Call.class); when(mockCall.execute()).thenThrow(expected); when(mockHttpClient.newCall(any(Request.class))).thenReturn(mockCall); try { new HttpClient(mockHttpClient).partialGet(url, ranges, Collections.<String, Credentials>emptyMap(), mockReceiver, listener); } catch (IOException exception) { assertEquals("IO", exception.getMessage()); } }
@SuppressWarnings("unchecked") @Test public void runtimeExceptionThrownForHttpResponsesOtherThan206() throws IOException, URISyntaxException { List<Integer> responsesToTest = Lists.newArrayList(500, 413); OkHttpClient mockHttpClient = mock(OkHttpClient.class); RangeReceiver mockReceiver = mock(RangeReceiver.class); RangeTransferListener listener = mock(RangeTransferListener.class); when(listener.newTransfer(any(List.class))).thenReturn(mock(HttpTransferListener.class)); List<ContentRange> ranges = this.createSomeRanges(1); URI url = new URI("http: for (Integer responseToTest : responsesToTest) { Call mockCall = mock(Call.class); Response fakeResponse = this.fakeResponse(responseToTest); when(mockHttpClient.newCall(any(Request.class))).thenReturn(mockCall); when(mockCall.execute()).thenReturn(fakeResponse); try { new HttpClient(mockHttpClient).partialGet(url, ranges, Collections.<String, Credentials>emptyMap(), mockReceiver, listener); } catch (HttpError exception) { assertEquals(responseToTest.intValue(), exception.getCode()); } } }