001: /*
002: * $HeadURL: https://svn.apache.org/repos/asf/httpcomponents/httpcore/tags/4.0-beta1/module-main/src/test/java/org/apache/http/impl/TestDefaultConnectionReuseStrategy.java $
003: * $Revision: 602506 $
004: * $Date: 2007-12-08 17:55:13 +0100 (Sat, 08 Dec 2007) $
005: * ====================================================================
006: * Licensed to the Apache Software Foundation (ASF) under one
007: * or more contributor license agreements. See the NOTICE file
008: * distributed with this work for additional information
009: * regarding copyright ownership. The ASF licenses this file
010: * to you under the Apache License, Version 2.0 (the
011: * "License"); you may not use this file except in compliance
012: * with the License. You may obtain a copy of the License at
013: *
014: * http://www.apache.org/licenses/LICENSE-2.0
015: *
016: * Unless required by applicable law or agreed to in writing,
017: * software distributed under the License is distributed on an
018: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
019: * KIND, either express or implied. See the License for the
020: * specific language governing permissions and limitations
021: * under the License.
022: * ====================================================================
023: *
024: * This software consists of voluntary contributions made by many
025: * individuals on behalf of the Apache Software Foundation. For more
026: * information on the Apache Software Foundation, please see
027: * <http://www.apache.org/>.
028: *
029: */
030:
031: package org.apache.http.impl;
032:
033: import org.apache.http.ConnectionReuseStrategy;
034: import org.apache.http.HttpConnection;
035: import org.apache.http.HttpConnectionMetrics;
036: import org.apache.http.HttpResponse;
037: import org.apache.http.HttpVersion;
038: import org.apache.http.StatusLine;
039: import org.apache.http.entity.BasicHttpEntity;
040: import org.apache.http.message.BasicHttpResponse;
041: import org.apache.http.message.BasicStatusLine;
042: import org.apache.http.protocol.HttpContext;
043: import org.apache.http.protocol.BasicHttpContext;
044: import org.apache.http.protocol.ExecutionContext;
045:
046: import junit.framework.Test;
047: import junit.framework.TestCase;
048: import junit.framework.TestSuite;
049:
050: public class TestDefaultConnectionReuseStrategy extends TestCase {
051:
052: /** A mock connection that is open and not stale. */
053: private HttpConnection mockConnection;
054:
055: /** HTTP context. */
056: private HttpContext context;
057:
058: /** The reuse strategy to be tested. */
059: private ConnectionReuseStrategy reuseStrategy;
060:
061: public TestDefaultConnectionReuseStrategy(String testName) {
062: super (testName);
063: }
064:
065: // ------------------------------------------------------- TestCase Methods
066:
067: public static Test suite() {
068: return new TestSuite(TestDefaultConnectionReuseStrategy.class);
069: }
070:
071: public void setUp() {
072: // open and not stale is required for most of the tests here
073: mockConnection = new MockConnection(true, false);
074: reuseStrategy = new DefaultConnectionReuseStrategy();
075: context = new BasicHttpContext(null);
076: context.setAttribute(ExecutionContext.HTTP_CONNECTION,
077: mockConnection);
078: }
079:
080: public void tearDown() {
081: mockConnection = null;
082: }
083:
084: // ------------------------------------------------------------------- Main
085: public static void main(String args[]) {
086: String[] testCaseName = { TestDefaultConnectionReuseStrategy.class
087: .getName() };
088: junit.textui.TestRunner.main(testCaseName);
089: }
090:
091: public void testIllegalResponseArg() throws Exception {
092:
093: HttpContext context = new BasicHttpContext(null);
094:
095: try {
096: reuseStrategy.keepAlive(null, context);
097: fail("IllegalArgumentException should have been thrown");
098: } catch (IllegalArgumentException ex) {
099: // expected
100: }
101: }
102:
103: public void testIllegalContextArg() throws Exception {
104: HttpResponse response = createResponse(HttpVersion.HTTP_1_1,
105: 200, "OK", false, -1);
106: try {
107: reuseStrategy.keepAlive(response, null);
108: fail("IllegalArgumentException should have been thrown");
109: } catch (IllegalArgumentException ex) {
110: // expected
111: }
112: }
113:
114: public void testNoContentLengthResponseHttp1_0() throws Exception {
115: HttpResponse response = createResponse(HttpVersion.HTTP_1_0,
116: 200, "OK", false, -1);
117:
118: assertFalse(reuseStrategy.keepAlive(response, context));
119: }
120:
121: public void testNoContentLengthResponseHttp1_1() throws Exception {
122: HttpResponse response = createResponse(HttpVersion.HTTP_1_1,
123: 200, "OK", false, -1);
124:
125: assertFalse(reuseStrategy.keepAlive(response, context));
126: }
127:
128: public void testChunkedContent() throws Exception {
129: HttpResponse response = createResponse(HttpVersion.HTTP_1_1,
130: 200, "OK", true, -1);
131:
132: assertTrue(reuseStrategy.keepAlive(response, context));
133: }
134:
135: public void testClosedConnection() throws Exception {
136:
137: // based on testChunkedContent which is known to return true
138: // the difference is in the mock connection passed here
139: HttpResponse response = createResponse(HttpVersion.HTTP_1_1,
140: 200, "OK", true, -1);
141:
142: HttpConnection mockonn = new MockConnection(false, false);
143: context.setAttribute(ExecutionContext.HTTP_CONNECTION, mockonn);
144: assertFalse("closed connection should not be kept alive",
145: reuseStrategy.keepAlive(response, context));
146: }
147:
148: public void testStaleConnection() throws Exception {
149:
150: // based on testChunkedContent which is known to return true
151: // the difference is in the mock connection passed here
152: HttpResponse response = createResponse(HttpVersion.HTTP_1_1,
153: 200, "OK", true, -1);
154:
155: HttpConnection mockonn = new MockConnection(true, true);
156: context.setAttribute(ExecutionContext.HTTP_CONNECTION, mockonn);
157: assertTrue("stale connection should not be detected",
158: reuseStrategy.keepAlive(response, context));
159: }
160:
161: public void testIgnoreInvalidKeepAlive() throws Exception {
162: HttpResponse response = createResponse(HttpVersion.HTTP_1_0,
163: 200, "OK", false, -1);
164: response.addHeader("Connection", "keep-alive");
165:
166: assertFalse(reuseStrategy.keepAlive(response, context));
167: }
168:
169: public void testExplicitClose() throws Exception {
170: // Use HTTP 1.1
171: HttpResponse response = createResponse(HttpVersion.HTTP_1_1,
172: 200, "OK", true, -1);
173: response.addHeader("Connection", "close");
174:
175: assertFalse(reuseStrategy.keepAlive(response, context));
176: }
177:
178: public void testExplicitKeepAlive() throws Exception {
179: // Use HTTP 1.0
180: HttpResponse response = createResponse(HttpVersion.HTTP_1_0,
181: 200, "OK", false, 10);
182: response.addHeader("Connection", "keep-alive");
183:
184: assertTrue(reuseStrategy.keepAlive(response, context));
185: }
186:
187: public void testHTTP10Default() throws Exception {
188: HttpResponse response = createResponse(HttpVersion.HTTP_1_0,
189: 200, "OK");
190:
191: assertFalse(reuseStrategy.keepAlive(response, context));
192: }
193:
194: public void testHTTP11Default() throws Exception {
195: HttpResponse response = createResponse(HttpVersion.HTTP_1_1,
196: 200, "OK");
197: assertTrue(reuseStrategy.keepAlive(response, context));
198: }
199:
200: public void testFutureHTTP() throws Exception {
201: HttpResponse response = createResponse(new HttpVersion(3, 45),
202: 200, "OK");
203:
204: assertTrue(reuseStrategy.keepAlive(response, context));
205: }
206:
207: public void testBrokenConnectionDirective1() throws Exception {
208: // Use HTTP 1.0
209: HttpResponse response = createResponse(HttpVersion.HTTP_1_0,
210: 200, "OK");
211: response.addHeader("Connection", "keep--alive");
212:
213: assertFalse(reuseStrategy.keepAlive(response, context));
214: }
215:
216: public void testBrokenConnectionDirective2() throws Exception {
217: // Use HTTP 1.0
218: HttpResponse response = createResponse(HttpVersion.HTTP_1_0,
219: 200, "OK");
220: response.addHeader("Connection", null);
221:
222: assertFalse(reuseStrategy.keepAlive(response, context));
223: }
224:
225: public void testConnectionTokens1() throws Exception {
226: // Use HTTP 1.1
227: HttpResponse response = createResponse(HttpVersion.HTTP_1_1,
228: 200, "OK", true, -1);
229: response.addHeader("Connection", "yadda, cLOSe, dumdy");
230:
231: assertFalse(reuseStrategy.keepAlive(response, context));
232: }
233:
234: public void testConnectionTokens2() throws Exception {
235: // Use HTTP 1.1
236: HttpResponse response = createResponse(HttpVersion.HTTP_1_1,
237: 200, "OK", true, -1);
238: response.addHeader("Connection", "yadda, kEEP-alive, dumdy");
239:
240: assertTrue(reuseStrategy.keepAlive(response, context));
241: }
242:
243: public void testConnectionTokens3() throws Exception {
244: // Use HTTP 1.1
245: HttpResponse response = createResponse(HttpVersion.HTTP_1_1,
246: 200, "OK", true, -1);
247: response.addHeader("Connection",
248: "yadda, keep-alive, close, dumdy");
249:
250: assertFalse(reuseStrategy.keepAlive(response, context));
251: }
252:
253: public void testConnectionTokens4() throws Exception {
254: // Use HTTP 1.1
255: HttpResponse response = createResponse(HttpVersion.HTTP_1_1,
256: 200, "OK", true, -1);
257: response.addHeader("Connection", "yadda, close, dumdy");
258: response.addHeader("Proxy-Connection", "keep-alive");
259:
260: // Connection takes precedence over Proxy-Connection
261: assertFalse(reuseStrategy.keepAlive(response, context));
262: }
263:
264: public void testConnectionTokens5() throws Exception {
265: // Use HTTP 1.1
266: HttpResponse response = createResponse(HttpVersion.HTTP_1_1,
267: 200, "OK", true, -1);
268: response.addHeader("Connection", "yadda, dumdy");
269: response.addHeader("Proxy-Connection", "close");
270:
271: // Connection takes precedence over Proxy-Connection,
272: // even if it doesn't contain a recognized token.
273: // Default for HTTP/1.1 is to keep alive.
274: assertTrue(reuseStrategy.keepAlive(response, context));
275: }
276:
277: public void testConnectionTokens6() throws Exception {
278: // Use HTTP 1.1
279: HttpResponse response = createResponse(HttpVersion.HTTP_1_1,
280: 200, "OK", true, -1);
281: response.addHeader("Connection", "");
282: response.addHeader("Proxy-Connection", "close");
283:
284: // Connection takes precedence over Proxy-Connection,
285: // even if it is empty. Default for HTTP/1.1 is to keep alive.
286: assertTrue(reuseStrategy.keepAlive(response, context));
287: }
288:
289: public void testConnectionTokensInvalid() throws Exception {
290: // Use HTTP 1.1
291: HttpResponse response = createResponse(HttpVersion.HTTP_1_1,
292: 200, "OK", true, -1);
293: response.addHeader("Connection", "keep-alive=true");
294:
295: assertFalse(reuseStrategy.keepAlive(response, context));
296: }
297:
298: /**
299: * Creates a response without an entity.
300: *
301: * @param version the HTTP version
302: * @param status the status code
303: * @param message the status message
304: *
305: * @return a response with the argument attributes, but no headers
306: */
307: private final static HttpResponse createResponse(
308: HttpVersion version, int status, String message) {
309:
310: StatusLine statusline = new BasicStatusLine(version, status,
311: message);
312: HttpResponse response = new BasicHttpResponse(statusline);
313:
314: return response;
315:
316: } // createResponse/empty
317:
318: /**
319: * Creates a response with an entity.
320: *
321: * @param version the HTTP version
322: * @param status the status code
323: * @param message the status message
324: * @param chunked whether the entity should indicate chunked encoding
325: * @param length the content length to be indicated by the entity
326: *
327: * @return a response with the argument attributes, but no headers
328: */
329: private final static HttpResponse createResponse(
330: HttpVersion version, int status, String message,
331: boolean chunked, int length) {
332:
333: BasicHttpEntity entity = new BasicHttpEntity();
334: entity.setChunked(chunked);
335: entity.setContentLength(length);
336: HttpResponse response = createResponse(version, status, message);
337: response.setEntity(entity);
338:
339: return response;
340:
341: } // createResponse/entity
342:
343: /**
344: * A mock connection.
345: * This is neither client nor server connection, since the default
346: * strategy is agnostic. It does not allow modification of it's state,
347: * since the strategy is supposed to decide about keep-alive, but not
348: * to modify the connection's state.
349: */
350: private final static class MockConnection implements HttpConnection {
351:
352: private boolean iAmOpen;
353: private boolean iAmStale;
354:
355: public MockConnection(boolean open, boolean stale) {
356: iAmOpen = open;
357: iAmStale = stale;
358: }
359:
360: public final boolean isOpen() {
361: return iAmOpen;
362: }
363:
364: public void setSocketTimeout(int timeout) {
365: }
366:
367: public int getSocketTimeout() {
368: return -1;
369: }
370:
371: public final boolean isStale() {
372: return iAmStale;
373: }
374:
375: public final void close() {
376: throw new UnsupportedOperationException(
377: "connection state must not be modified");
378: }
379:
380: public final void shutdown() {
381: throw new UnsupportedOperationException(
382: "connection state must not be modified");
383: }
384:
385: public HttpConnectionMetrics getMetrics() {
386: return null;
387: }
388:
389: } // class MockConnection
390:
391: } // class TestDefaultConnectionReuseStrategy
|