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 183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.io.ByteArrayOutputStream; 19a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamathimport java.io.IOException; 203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.net.URL; 21a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamathimport java.util.ArrayList; 22c6bd683320121544811f481709b3fdbcbe9b3866Neil Fullerimport java.util.Iterator; 233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.LinkedHashMap; 24a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamathimport java.util.List; 253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.Map; 26a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamathimport java.util.concurrent.TimeUnit; 27a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath 28a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath/** 29a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * Records received HTTP responses so they can be later retrieved by tests. 30a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath */ 31a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamathpublic class RecordingReceiver implements Response.Receiver { 32a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath public static final long TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(10); 33a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath 343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller private final Map<Response, ByteArrayOutputStream> inFlightResponses 353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller = new LinkedHashMap<Response, ByteArrayOutputStream>(); 36a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath private final List<RecordedResponse> responses = new ArrayList<RecordedResponse>(); 37a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath 38a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath @Override public synchronized void onFailure(Failure failure) { 39a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath responses.add(new RecordedResponse(failure.request(), null, null, failure)); 40a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath notifyAll(); 41a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath } 42a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath 433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Override public synchronized boolean onResponse(Response response) throws IOException { 443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller ByteArrayOutputStream out = inFlightResponses.get(response); 453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller if (out == null) { 463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller out = new ByteArrayOutputStream(); 473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller inFlightResponses.put(response, out); 483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller byte[] buffer = new byte[1024]; 513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller Response.Body body = response.body(); 523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller while (body.ready()) { 543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller int c = body.byteStream().read(buffer); 553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller if (c == -1) { 573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller inFlightResponses.remove(response); 583c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller responses.add(new RecordedResponse( 593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller response.request(), response, out.toString("UTF-8"), null)); 603c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller notifyAll(); 613c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return true; 623c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 633c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 643c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller out.write(buffer, 0, c); 653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 663c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return false; 68a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath } 69a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath 70a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath /** 71a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * Returns the recorded response triggered by {@code request}. Throws if the 72a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * response isn't enqueued before the timeout. 73a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath */ 743c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller public synchronized RecordedResponse await(URL url) throws Exception { 75a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath long timeoutMillis = TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) + TIMEOUT_MILLIS; 76a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath while (true) { 77c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller for (Iterator<RecordedResponse> i = responses.iterator(); i.hasNext(); ) { 78c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller RecordedResponse recordedResponse = i.next(); 793c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller if (recordedResponse.request.url().equals(url)) { 80c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller i.remove(); 81a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath return recordedResponse; 82a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath } 83a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath } 84a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath 85a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath long nowMillis = TimeUnit.NANOSECONDS.toMillis(System.nanoTime()); 86a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath if (nowMillis >= timeoutMillis) break; 87a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath wait(timeoutMillis - nowMillis); 88a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath } 89a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath 903c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller throw new AssertionError("Timed out waiting for response to " + url); 913c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 923c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 933c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller public synchronized void assertNoResponse(URL url) throws Exception { 943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller for (RecordedResponse recordedResponse : responses) { 953c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller if (recordedResponse.request.url().equals(url)) { 963c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller throw new AssertionError("Expected no response for " + url); 973c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 983c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 99a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath } 100a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath} 101