1b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson/* 2b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * Copyright (C) 2010 The Android Open Source Project 3b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * 4b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 5b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * you may not use this file except in compliance with the License. 6b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * You may obtain a copy of the License at 7b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * 8b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 9b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * 10b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * Unless required by applicable law or agreed to in writing, software 11b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 12b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * See the License for the specific language governing permissions and 14b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * limitations under the License. 15b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson */ 16b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 17b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilsonpackage tests.http; 18b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 19b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilsonimport java.io.ByteArrayOutputStream; 20b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilsonimport java.io.IOException; 21b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilsonimport java.io.UnsupportedEncodingException; 22b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilsonimport java.util.ArrayList; 23b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilsonimport java.util.List; 24b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilsonimport static tests.http.MockWebServer.ASCII; 25b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 26b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson/** 27b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * A scripted response to be replayed by the mock web server. 28b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson */ 290c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilsonpublic class MockResponse implements Cloneable { 300c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson private static final String RFC_1123_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss zzz"; 31b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson private static final String EMPTY_BODY_HEADER = "Content-Length: 0"; 32b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson private static final String CHUNKED_BODY_HEADER = "Transfer-encoding: chunked"; 33b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson private static final byte[] EMPTY_BODY = new byte[0]; 34b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 35b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson private String status = "HTTP/1.1 200 OK"; 36b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson private List<String> headers = new ArrayList<String>(); 37b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson private byte[] body = EMPTY_BODY; 38e942f46f10bb9384a1b186b3d7b74f9704c57090Jesse Wilson private SocketPolicy socketPolicy = SocketPolicy.KEEP_OPEN; 39b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 40b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson public MockResponse() { 41b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson headers.add(EMPTY_BODY_HEADER); 42b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 43b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 440c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson @Override public MockResponse clone() { 450c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson try { 460c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson MockResponse result = (MockResponse) super.clone(); 470c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson result.headers = new ArrayList<String>(result.headers); 480c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson return result; 490c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } catch (CloneNotSupportedException e) { 500c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson throw new AssertionError(); 510c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 520c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson } 530c59055dd24e1659f85d9ff7e2148883f663bd62Jesse Wilson 54b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson /** 55b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * Returns the HTTP response line, such as "HTTP/1.1 200 OK". 56b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson */ 57b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson public String getStatus() { 58b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson return status; 59b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 60b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 61b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson public MockResponse setResponseCode(int code) { 62b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson this.status = "HTTP/1.1 " + code + " OK"; 63b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson return this; 64b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 65b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 66706d53593cd8841d378dbe298a8d1940db1e71dfJesse Wilson public MockResponse setStatus(String status) { 67706d53593cd8841d378dbe298a8d1940db1e71dfJesse Wilson this.status = status; 68706d53593cd8841d378dbe298a8d1940db1e71dfJesse Wilson return this; 69706d53593cd8841d378dbe298a8d1940db1e71dfJesse Wilson } 70706d53593cd8841d378dbe298a8d1940db1e71dfJesse Wilson 71b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson /** 72b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * Returns the HTTP headers, such as "Content-Length: 0". 73b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson */ 74b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson public List<String> getHeaders() { 75b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson return headers; 76b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 77b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 78c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson public MockResponse clearHeaders() { 79c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson headers.clear(); 80c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson return this; 81c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson } 82c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson 83b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson public MockResponse addHeader(String header) { 84b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson headers.add(header); 85b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson return this; 86b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 87b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 88b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson /** 89b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson * Returns an input stream containing the raw HTTP payload. 90b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson */ 91b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson public byte[] getBody() { 92b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson return body; 93b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 94b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 95b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson public MockResponse setBody(byte[] body) { 96b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson if (this.body == EMPTY_BODY) { 97b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson headers.remove(EMPTY_BODY_HEADER); 98b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 99b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson this.headers.add("Content-Length: " + body.length); 100b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson this.body = body; 101b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson return this; 102b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 103b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 104b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson public MockResponse setBody(String body) { 105b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson try { 106b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson return setBody(body.getBytes(ASCII)); 107b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } catch (UnsupportedEncodingException e) { 108b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson throw new AssertionError(); 109b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 110b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 111b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 112b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson public MockResponse setChunkedBody(byte[] body, int maxChunkSize) throws IOException { 113b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson headers.remove(EMPTY_BODY_HEADER); 114b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson headers.add(CHUNKED_BODY_HEADER); 115b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 116b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); 117b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson int pos = 0; 118b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson while (pos < body.length) { 119b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson int chunkSize = Math.min(body.length - pos, maxChunkSize); 120b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson bytesOut.write(Integer.toHexString(chunkSize).getBytes(ASCII)); 121b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson bytesOut.write("\r\n".getBytes(ASCII)); 122b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson bytesOut.write(body, pos, chunkSize); 123b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson bytesOut.write("\r\n".getBytes(ASCII)); 124b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson pos += chunkSize; 125b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 126c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson bytesOut.write("0\r\n\r\n".getBytes(ASCII)); // last chunk + empty trailer + crlf 127b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson this.body = bytesOut.toByteArray(); 128b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson return this; 129b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 130b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 131b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson public MockResponse setChunkedBody(String body, int maxChunkSize) throws IOException { 132b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson return setChunkedBody(body.getBytes(ASCII), maxChunkSize); 133b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 134b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 135e942f46f10bb9384a1b186b3d7b74f9704c57090Jesse Wilson public SocketPolicy getSocketPolicy() { 136e942f46f10bb9384a1b186b3d7b74f9704c57090Jesse Wilson return socketPolicy; 1374559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 1384559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom 139e942f46f10bb9384a1b186b3d7b74f9704c57090Jesse Wilson public MockResponse setSocketPolicy(SocketPolicy socketPolicy) { 140e942f46f10bb9384a1b186b3d7b74f9704c57090Jesse Wilson this.socketPolicy = socketPolicy; 14151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson return this; 14251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 14351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 144b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson @Override public String toString() { 145b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson return status; 146b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 147b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson} 148