1a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath/*
2a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * Copyright (C) 2013 Square, Inc.
3a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath *
4a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * Licensed under the Apache License, Version 2.0 (the "License");
5a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * you may not use this file except in compliance with the License.
6a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * You may obtain a copy of the License at
7a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath *
8a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath *      http://www.apache.org/licenses/LICENSE-2.0
9a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath *
10a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * Unless required by applicable law or agreed to in writing, software
11a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * distributed under the License is distributed on an "AS IS" BASIS,
12a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * See the License for the specific language governing permissions and
14a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * limitations under the License.
15a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath */
16166772be0e5cfdaea1a64b9f63e4c8dbfe48cba3Narayan Kamathpackage com.squareup.okhttp;
17a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
18a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamathimport java.io.IOException;
19a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamathimport java.util.ArrayList;
20c6bd683320121544811f481709b3fdbcbe9b3866Neil Fullerimport java.util.Iterator;
21a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamathimport java.util.List;
22a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamathimport java.util.concurrent.TimeUnit;
23e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport okio.Buffer;
24a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
25a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath/**
26a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * Records received HTTP responses so they can be later retrieved by tests.
27a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath */
28e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerpublic class RecordingCallback implements Callback {
29a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  public static final long TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(10);
30a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
31e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  private final List<RecordedResponse> responses = new ArrayList<>();
32a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
33e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Override public synchronized void onFailure(Request request, IOException e) {
34e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    responses.add(new RecordedResponse(request, null, null, null, e));
35a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath    notifyAll();
36a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  }
37a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
38e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Override public synchronized void onResponse(Response response) throws IOException {
39e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Buffer buffer = new Buffer();
40e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    ResponseBody body = response.body();
41e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    body.source().readAll(buffer);
423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
43e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    responses.add(new RecordedResponse(response.request(), response, null, buffer.readUtf8(), null));
44e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    notifyAll();
45a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  }
46a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
47a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  /**
48a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath   * Returns the recorded response triggered by {@code request}. Throws if the
49a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath   * response isn't enqueued before the timeout.
50a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath   */
5171b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller  public synchronized RecordedResponse await(HttpUrl url) throws Exception {
52a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath    long timeoutMillis = TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) + TIMEOUT_MILLIS;
53a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath    while (true) {
54c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller      for (Iterator<RecordedResponse> i = responses.iterator(); i.hasNext(); ) {
55c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller        RecordedResponse recordedResponse = i.next();
5671b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller        if (recordedResponse.request.httpUrl().equals(url)) {
57c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller          i.remove();
58a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath          return recordedResponse;
59a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath        }
60a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath      }
61a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
62a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath      long nowMillis = TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
63a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath      if (nowMillis >= timeoutMillis) break;
64a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath      wait(timeoutMillis - nowMillis);
65a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath    }
66a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    throw new AssertionError("Timed out waiting for response to " + url);
683c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
7071b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller  public synchronized void assertNoResponse(HttpUrl url) throws Exception {
713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    for (RecordedResponse recordedResponse : responses) {
7271b9f47b26fb57ac3e436a19519c6e3ec70e86ebNeil Fuller      if (recordedResponse.request.httpUrl().equals(url)) {
733c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        throw new AssertionError("Expected no response for " + url);
743c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
753c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
76a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  }
77a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath}
78