Added test cases for EofSensorInputStream, ConnectionReleaseTriggerImpl, RequestEntityWrapper, ResponseEntityWrapper

git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1405557 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Oleg Kalnichevski 2012-11-04 15:27:45 +00:00
parent 87a46db5c2
commit d550a62fe3
11 changed files with 702 additions and 131 deletions

View File

@ -33,14 +33,8 @@ import org.apache.http.annotation.NotThreadSafe;
/** /**
* A stream wrapper that triggers actions on {@link #close close()} and EOF. * A stream wrapper that triggers actions on {@link #close close()} and EOF.
* Primarily used to auto-release an underlying * Primarily used to auto-release an underlying managed connection when the response
* {@link ManagedClientConnection connection} * body is consumed or no longer needed.
* when the response body is consumed or no longer needed.
* <p>
* This class is based on <code>AutoCloseInputStream</code> in HttpClient 3.1,
* but has notable differences. It does not allow mark/reset, distinguishes
* different kinds of event, and does not always close the underlying stream
* on EOF. That decision is left to the {@link EofSensorWatcher watcher}.
* *
* @see EofSensorWatcher * @see EofSensorWatcher
* *
@ -87,15 +81,21 @@ public class EofSensorInputStream extends InputStream implements ConnectionRelea
public EofSensorInputStream(final InputStream in, public EofSensorInputStream(final InputStream in,
final EofSensorWatcher watcher) { final EofSensorWatcher watcher) {
if (in == null) { if (in == null) {
throw new IllegalArgumentException throw new IllegalArgumentException("Wrapped stream may not be null");
("Wrapped stream may not be null.");
} }
wrappedStream = in; wrappedStream = in;
selfClosed = false; selfClosed = false;
eofWatcher = watcher; eofWatcher = watcher;
} }
boolean isSelfClosed() {
return selfClosed;
}
InputStream getWrappedStream() {
return wrappedStream;
}
/** /**
* Checks whether the underlying stream can be read from. * Checks whether the underlying stream can be read from.
* *
@ -148,18 +148,7 @@ public class EofSensorInputStream extends InputStream implements ConnectionRelea
@Override @Override
public int read(byte[] b) throws IOException { public int read(byte[] b) throws IOException {
int l = -1; return read(b, 0, b.length);
if (isReadAllowed()) {
try {
l = wrappedStream.read(b);
checkEOF(l);
} catch (IOException ex) {
checkAbort();
throw ex;
}
}
return l;
} }
@Override @Override

View File

@ -95,8 +95,22 @@ class ConnectionReleaseTriggerImpl implements ConnectionReleaseTrigger, Cancella
return; return;
} }
this.released = true; this.released = true;
if (this.reusable) {
this.manager.releaseConnection(this.managedConn, this.manager.releaseConnection(this.managedConn,
this.state, this.validDuration, this.tunit); this.state, this.validDuration, this.tunit);
} else {
try {
this.managedConn.close();
log.debug("Connection discarded");
} catch (IOException ex) {
if (this.log.isDebugEnabled()) {
this.log.debug(ex.getMessage(), ex);
}
} finally {
this.manager.releaseConnection(
this.managedConn, null, 0, TimeUnit.MILLISECONDS);
}
}
} }
} }

View File

@ -27,11 +27,7 @@
package org.apache.http.impl.client.builder; package org.apache.http.impl.client.builder;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException;
import org.apache.http.annotation.NotThreadSafe; import org.apache.http.annotation.NotThreadSafe;
@ -44,10 +40,8 @@ import org.apache.http.ProtocolException;
import org.apache.http.ProtocolVersion; import org.apache.http.ProtocolVersion;
import org.apache.http.RequestLine; import org.apache.http.RequestLine;
import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.HttpEntityWrapper;
import org.apache.http.message.AbstractHttpMessage; import org.apache.http.message.AbstractHttpMessage;
import org.apache.http.message.BasicRequestLine; import org.apache.http.message.BasicRequestLine;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP; import org.apache.http.protocol.HTTP;
/** /**
@ -62,34 +56,22 @@ class HttpRequestWrapper extends AbstractHttpMessage implements HttpRequest {
private final HttpRequest original; private final HttpRequest original;
private URI uri; private URI uri;
private String method;
private ProtocolVersion version;
private HttpHost virtualHost; private HttpHost virtualHost;
private HttpRequestWrapper( private HttpRequestWrapper(final HttpRequest request) {
final ProtocolVersion version,
final URI uri,
final String method,
final HttpRequest request) {
super(); super();
this.original = request; this.original = request;
this.uri = uri; if (request instanceof HttpUriRequest) {
this.method = method; this.uri = ((HttpUriRequest) request).getURI();
this.version = version; } else {
this.uri = null;
}
setParams(request.getParams()); setParams(request.getParams());
setHeaders(request.getAllHeaders()); setHeaders(request.getAllHeaders());
} }
public ProtocolVersion getProtocolVersion() { public ProtocolVersion getProtocolVersion() {
if (this.version != null) { return this.original.getProtocolVersion();
return this.version;
} else {
return HttpProtocolParams.getVersion(getParams());
}
}
public void setProtocolVersion(final ProtocolVersion version) {
this.version = version;
} }
public URI getURI() { public URI getURI() {
@ -101,18 +83,18 @@ class HttpRequestWrapper extends AbstractHttpMessage implements HttpRequest {
} }
public RequestLine getRequestLine() { public RequestLine getRequestLine() {
ProtocolVersion version = this.original.getRequestLine().getProtocolVersion();
String method = this.original.getRequestLine().getMethod();
String uritext = null; String uritext = null;
if (this.uri != null) { if (this.uri != null) {
uritext = uri.toASCIIString(); uritext = this.uri.toASCIIString();
} else {
uritext = this.original.getRequestLine().getUri();
} }
if (uritext == null || uritext.length() == 0) { if (uritext == null || uritext.length() == 0) {
uritext = "/"; uritext = "/";
} }
return new BasicRequestLine(this.method, uritext, getProtocolVersion()); return new BasicRequestLine(method, uritext, version);
}
public String getMethod() {
return this.method;
} }
public HttpRequest getOriginal() { public HttpRequest getOriginal() {
@ -133,22 +115,17 @@ class HttpRequestWrapper extends AbstractHttpMessage implements HttpRequest {
@Override @Override
public String toString() { public String toString() {
return this.method + " " + this.uri + " " + this.headergroup; return getRequestLine() + " " + this.headergroup;
} }
static class HttpEntityEnclosingRequestWrapper extends HttpRequestWrapper static class HttpEntityEnclosingRequestWrapper extends HttpRequestWrapper
implements HttpEntityEnclosingRequest { implements HttpEntityEnclosingRequest {
private HttpEntity entity; private HttpEntity entity;
private boolean consumed;
public HttpEntityEnclosingRequestWrapper( public HttpEntityEnclosingRequestWrapper(final HttpEntityEnclosingRequest request)
final ProtocolVersion version,
final URI uri,
final String method,
final HttpEntityEnclosingRequest request)
throws ProtocolException { throws ProtocolException {
super(version, uri, method, request); super(request);
setEntity(request.getEntity()); setEntity(request.getEntity());
} }
@ -157,7 +134,7 @@ class HttpRequestWrapper extends AbstractHttpMessage implements HttpRequest {
} }
public void setEntity(final HttpEntity entity) { public void setEntity(final HttpEntity entity) {
this.entity = entity != null ? new EntityWrapper(entity) : null; this.entity = entity != null ? new RequestEntityWrapper(entity) : null;
} }
public boolean expectContinue() { public boolean expectContinue() {
@ -167,32 +144,7 @@ class HttpRequestWrapper extends AbstractHttpMessage implements HttpRequest {
@Override @Override
public boolean isRepeatable() { public boolean isRepeatable() {
return this.entity == null || this.entity.isRepeatable() || !this.consumed; return this.entity == null || this.entity.isRepeatable();
}
class EntityWrapper extends HttpEntityWrapper {
EntityWrapper(final HttpEntity entity) {
super(entity);
}
@Deprecated
@Override
public void consumeContent() throws IOException {
consumed = true;
super.consumeContent();
}
@Override
public InputStream getContent() throws IOException {
return super.getContent();
}
@Override
public void writeTo(final OutputStream outstream) throws IOException {
consumed = true;
super.writeTo(outstream);
}
} }
} }
@ -201,28 +153,10 @@ class HttpRequestWrapper extends AbstractHttpMessage implements HttpRequest {
if (request == null) { if (request == null) {
return null; return null;
} }
ProtocolVersion version;
URI uri;
String method;
if (request instanceof HttpUriRequest) {
version = ((HttpUriRequest) request).getProtocolVersion();
uri = ((HttpUriRequest) request).getURI();
method = ((HttpUriRequest) request).getMethod();
} else {
RequestLine requestLine = request.getRequestLine();
version = request.getProtocolVersion();
try {
uri = new URI(requestLine.getUri());
} catch (URISyntaxException ex) {
throw new ProtocolException("Invalid request URI: " + requestLine.getUri(), ex);
}
method = request.getRequestLine().getMethod();
}
if (request instanceof HttpEntityEnclosingRequest) { if (request instanceof HttpEntityEnclosingRequest) {
return new HttpEntityEnclosingRequestWrapper(version, uri, method, return new HttpEntityEnclosingRequestWrapper((HttpEntityEnclosingRequest) request);
(HttpEntityEnclosingRequest) request);
} else { } else {
return new HttpRequestWrapper(version, uri, method, request); return new HttpRequestWrapper(request);
} }
} }

View File

@ -78,6 +78,7 @@ class ProtocolExec implements ClientExecChain {
final HttpRoute route) throws ProtocolException { final HttpRoute route) throws ProtocolException {
try { try {
URI uri = request.getURI(); URI uri = request.getURI();
if (uri != null) {
if (route.getProxyHost() != null && !route.isTunnelled()) { if (route.getProxyHost() != null && !route.isTunnelled()) {
// Make sure the request URI is absolute // Make sure the request URI is absolute
if (!uri.isAbsolute()) { if (!uri.isAbsolute()) {
@ -95,6 +96,7 @@ class ProtocolExec implements ClientExecChain {
} }
} }
request.setURI(uri); request.setURI(uri);
}
} catch (URISyntaxException ex) { } catch (URISyntaxException ex) {
throw new ProtocolException("Invalid URI: " + throw new ProtocolException("Invalid URI: " +
request.getRequestLine().getUri(), ex); request.getRequestLine().getUri(), ex);

View File

@ -0,0 +1,50 @@
package org.apache.http.impl.client.builder;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.http.HttpEntity;
import org.apache.http.annotation.NotThreadSafe;
import org.apache.http.entity.HttpEntityWrapper;
/**
* A wrapper class for {@link HttpEntity} enclosed in a request message.
*
* @since 4.3
*/
@NotThreadSafe
class RequestEntityWrapper extends HttpEntityWrapper {
private boolean consumed = false;
RequestEntityWrapper(final HttpEntity entity) {
super(entity);
}
@Override
public boolean isRepeatable() {
if (!this.consumed) {
return true;
} else {
return super.isRepeatable();
}
}
@Deprecated
@Override
public void consumeContent() throws IOException {
consumed = true;
super.consumeContent();
}
@Override
public void writeTo(final OutputStream outstream) throws IOException {
consumed = true;
super.writeTo(outstream);
}
public boolean isConsumed() {
return consumed;
}
}

View File

@ -37,10 +37,9 @@ import org.apache.http.annotation.NotThreadSafe;
import org.apache.http.conn.EofSensorInputStream; import org.apache.http.conn.EofSensorInputStream;
import org.apache.http.conn.EofSensorWatcher; import org.apache.http.conn.EofSensorWatcher;
import org.apache.http.entity.HttpEntityWrapper; import org.apache.http.entity.HttpEntityWrapper;
import org.apache.http.util.EntityUtils;
/** /**
* A wrapper class for {@link HttpEntity} encloded in a response message. * A wrapper class for {@link HttpEntity} enclosed in a response message.
* *
* @since 4.3 * @since 4.3
*/ */
@ -66,7 +65,6 @@ class ResponseEntityWrapper extends HttpEntityWrapper implements EofSensorWatche
if (this.connReleaseTrigger != null) { if (this.connReleaseTrigger != null) {
try { try {
if (this.connReleaseTrigger.isReusable()) { if (this.connReleaseTrigger.isReusable()) {
EntityUtils.consume(this.wrappedEntity);
this.connReleaseTrigger.releaseConnection(); this.connReleaseTrigger.releaseConnection();
} }
} finally { } finally {
@ -93,8 +91,12 @@ class ResponseEntityWrapper extends HttpEntityWrapper implements EofSensorWatche
@Override @Override
public void writeTo(final OutputStream outstream) throws IOException { public void writeTo(final OutputStream outstream) throws IOException {
try {
this.wrappedEntity.writeTo(outstream); this.wrappedEntity.writeTo(outstream);
releaseConnection(); releaseConnection();
} finally {
cleanup();
}
} }
public boolean eofDetected(final InputStream wrapped) throws IOException { public boolean eofDetected(final InputStream wrapped) throws IOException {

View File

@ -0,0 +1,227 @@
/*
* ====================================================================
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.conn;
import java.io.IOException;
import java.io.InputStream;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
public class TestEofSensorInputStream {
private InputStream instream;
private EofSensorWatcher eofwatcher;
private EofSensorInputStream eofstream;
@Before
public void setup() throws Exception {
instream = Mockito.mock(InputStream.class);
eofwatcher = Mockito.mock(EofSensorWatcher.class);
eofstream = new EofSensorInputStream(instream, eofwatcher);
}
@Test
public void testClose() throws Exception {
Mockito.when(eofwatcher.streamClosed(Mockito.<InputStream>any())).thenReturn(true);
eofstream.close();
Assert.assertTrue(eofstream.isSelfClosed());
Assert.assertNull(eofstream.getWrappedStream());
Mockito.verify(instream, Mockito.times(1)).close();
Mockito.verify(eofwatcher).streamClosed(instream);
eofstream.close();
}
@Test
public void testCloseIOError() throws Exception {
Mockito.when(eofwatcher.streamClosed(Mockito.<InputStream>any())).thenThrow(new IOException());
try {
eofstream.close();
Assert.fail("IOException expected");
} catch (IOException ex) {
}
Assert.assertTrue(eofstream.isSelfClosed());
Assert.assertNull(eofstream.getWrappedStream());
Mockito.verify(eofwatcher).streamClosed(instream);
}
@Test
public void testReleaseConnection() throws Exception {
Mockito.when(eofwatcher.streamClosed(Mockito.<InputStream>any())).thenReturn(true);
eofstream.releaseConnection();
Assert.assertTrue(eofstream.isSelfClosed());
Assert.assertNull(eofstream.getWrappedStream());
Mockito.verify(instream, Mockito.times(1)).close();
Mockito.verify(eofwatcher).streamClosed(instream);
eofstream.releaseConnection();
}
@Test
public void testAbortConnection() throws Exception {
Mockito.when(eofwatcher.streamAbort(Mockito.<InputStream>any())).thenReturn(true);
eofstream.abortConnection();
Assert.assertTrue(eofstream.isSelfClosed());
Assert.assertNull(eofstream.getWrappedStream());
Mockito.verify(instream, Mockito.times(1)).close();
Mockito.verify(eofwatcher).streamAbort(instream);
eofstream.abortConnection();
}
@Test
public void testAbortConnectionIOError() throws Exception {
Mockito.when(eofwatcher.streamAbort(Mockito.<InputStream>any())).thenThrow(new IOException());
try {
eofstream.abortConnection();
Assert.fail("IOException expected");
} catch (IOException ex) {
}
Assert.assertTrue(eofstream.isSelfClosed());
Assert.assertNull(eofstream.getWrappedStream());
Mockito.verify(eofwatcher).streamAbort(instream);
}
@Test
public void testRead() throws Exception {
Mockito.when(eofwatcher.eofDetected(Mockito.<InputStream>any())).thenReturn(true);
Mockito.when(instream.read()).thenReturn(0, -1);
Assert.assertEquals(0, eofstream.read());
Assert.assertFalse(eofstream.isSelfClosed());
Assert.assertNotNull(eofstream.getWrappedStream());
Mockito.verify(eofwatcher, Mockito.never()).eofDetected(instream);
Assert.assertEquals(-1, eofstream.read());
Assert.assertFalse(eofstream.isSelfClosed());
Assert.assertNull(eofstream.getWrappedStream());
Mockito.verify(instream, Mockito.times(1)).close();
Mockito.verify(eofwatcher).eofDetected(instream);
Assert.assertEquals(-1, eofstream.read());
}
@Test
public void testReadIOError() throws Exception {
Mockito.when(eofwatcher.eofDetected(Mockito.<InputStream>any())).thenReturn(true);
Mockito.when(instream.read()).thenThrow(new IOException());
try {
eofstream.read();
Assert.fail("IOException expected");
} catch (IOException ex) {
}
Assert.assertFalse(eofstream.isSelfClosed());
Assert.assertNull(eofstream.getWrappedStream());
Mockito.verify(eofwatcher).streamAbort(instream);
}
@Test
public void testReadByteArray() throws Exception {
Mockito.when(eofwatcher.eofDetected(Mockito.<InputStream>any())).thenReturn(true);
Mockito.when(instream.read(Mockito.<byte []>any(), Mockito.anyInt(), Mockito.anyInt()))
.thenReturn(1, -1);
byte[] tmp = new byte[1];
Assert.assertEquals(1, eofstream.read(tmp));
Assert.assertFalse(eofstream.isSelfClosed());
Assert.assertNotNull(eofstream.getWrappedStream());
Mockito.verify(eofwatcher, Mockito.never()).eofDetected(instream);
Assert.assertEquals(-1, eofstream.read(tmp));
Assert.assertFalse(eofstream.isSelfClosed());
Assert.assertNull(eofstream.getWrappedStream());
Mockito.verify(instream, Mockito.times(1)).close();
Mockito.verify(eofwatcher).eofDetected(instream);
Assert.assertEquals(-1, eofstream.read(tmp));
}
@Test
public void testReadByteArrayIOError() throws Exception {
Mockito.when(eofwatcher.eofDetected(Mockito.<InputStream>any())).thenReturn(true);
Mockito.when(instream.read(Mockito.<byte []>any(), Mockito.anyInt(), Mockito.anyInt()))
.thenThrow(new IOException());
byte[] tmp = new byte[1];
try {
eofstream.read(tmp);
Assert.fail("IOException expected");
} catch (IOException ex) {
}
Assert.assertFalse(eofstream.isSelfClosed());
Assert.assertNull(eofstream.getWrappedStream());
Mockito.verify(eofwatcher).streamAbort(instream);
}
@Test
public void testReadAfterAbort() throws Exception {
Mockito.when(eofwatcher.streamAbort(Mockito.<InputStream>any())).thenReturn(true);
eofstream.abortConnection();
try {
eofstream.read();
Assert.fail("IOException expected");
} catch (IOException ex) {
}
byte[] tmp = new byte[1];
try {
eofstream.read(tmp);
Assert.fail("IOException expected");
} catch (IOException ex) {
}
}
}

View File

@ -0,0 +1,150 @@
/*
* ====================================================================
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.impl.client.builder;
import junit.framework.Assert;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import org.apache.commons.logging.Log;
import org.apache.http.HttpClientConnection;
import org.apache.http.conn.HttpClientConnectionManager;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
public class TestConnectionReleaseTriggerImpl {
private Log log;
private HttpClientConnectionManager mgr;
private HttpClientConnection conn;
private ConnectionReleaseTriggerImpl releaseTrigger;
@Before
public void setup() {
log = Mockito.mock(Log.class);
mgr = Mockito.mock(HttpClientConnectionManager.class);
conn = Mockito.mock(HttpClientConnection.class);
releaseTrigger = new ConnectionReleaseTriggerImpl(log, mgr, conn);
}
@Test
public void testAbortConnection() throws Exception {
releaseTrigger.abortConnection();
Assert.assertTrue(releaseTrigger.isReleased());
Mockito.verify(conn).shutdown();
Mockito.verify(mgr).releaseConnection(conn, null, 0, TimeUnit.MILLISECONDS);
releaseTrigger.abortConnection();
Mockito.verify(conn, Mockito.times(1)).shutdown();
Mockito.verify(mgr, Mockito.times(1)).releaseConnection(
Mockito.<HttpClientConnection>any(),
Mockito.anyObject(),
Mockito.anyLong(),
Mockito.<TimeUnit>any());
}
@Test
public void testAbortConnectionIOError() throws Exception {
Mockito.doThrow(new IOException()).when(conn).shutdown();
releaseTrigger.abortConnection();
Assert.assertTrue(releaseTrigger.isReleased());
Mockito.verify(conn).shutdown();
Mockito.verify(mgr).releaseConnection(conn, null, 0, TimeUnit.MILLISECONDS);
}
@Test
public void testCancell() throws Exception {
Assert.assertTrue(releaseTrigger.cancel());
Assert.assertTrue(releaseTrigger.isReleased());
Mockito.verify(conn).shutdown();
Mockito.verify(mgr).releaseConnection(conn, null, 0, TimeUnit.MILLISECONDS);
Assert.assertFalse(releaseTrigger.cancel());
Mockito.verify(conn, Mockito.times(1)).shutdown();
Mockito.verify(mgr, Mockito.times(1)).releaseConnection(
Mockito.<HttpClientConnection>any(),
Mockito.anyObject(),
Mockito.anyLong(),
Mockito.<TimeUnit>any());
}
@Test
public void testReleaseConnectionReusable() throws Exception {
releaseTrigger.setState("some state");
releaseTrigger.setValidFor(100, TimeUnit.SECONDS);
releaseTrigger.markReusable();
releaseTrigger.releaseConnection();
Assert.assertTrue(releaseTrigger.isReleased());
Mockito.verify(conn, Mockito.never()).close();
Mockito.verify(mgr).releaseConnection(conn, "some state", 100, TimeUnit.SECONDS);
releaseTrigger.releaseConnection();
Mockito.verify(mgr, Mockito.times(1)).releaseConnection(
Mockito.<HttpClientConnection>any(),
Mockito.anyObject(),
Mockito.anyLong(),
Mockito.<TimeUnit>any());
}
@Test
public void testReleaseConnectionNonReusable() throws Exception {
releaseTrigger.setState("some state");
releaseTrigger.setValidFor(100, TimeUnit.SECONDS);
releaseTrigger.markNonReusable();
releaseTrigger.releaseConnection();
Assert.assertTrue(releaseTrigger.isReleased());
Mockito.verify(conn, Mockito.times(1)).close();
Mockito.verify(mgr).releaseConnection(conn, null, 0, TimeUnit.MILLISECONDS);
releaseTrigger.releaseConnection();
Mockito.verify(mgr, Mockito.times(1)).releaseConnection(
Mockito.<HttpClientConnection>any(),
Mockito.anyObject(),
Mockito.anyLong(),
Mockito.<TimeUnit>any());
}
}

View File

@ -0,0 +1,63 @@
/*
* ====================================================================
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.impl.client.builder;
import java.io.OutputStream;
import junit.framework.Assert;
import org.apache.http.HttpEntity;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
public class TestRequestEntityWrapper {
private HttpEntity entity;
private RequestEntityWrapper wrapper;
@Before
public void setup() throws Exception {
entity = Mockito.mock(HttpEntity.class);;
wrapper = new RequestEntityWrapper(entity);
}
@Test
public void testNonRepeatableEntityWriteTo() throws Exception {
Mockito.when(entity.isRepeatable()).thenReturn(false);
Assert.assertTrue(wrapper.isRepeatable());
OutputStream outstream = Mockito.mock(OutputStream.class);
wrapper.writeTo(outstream);
Assert.assertTrue(wrapper.isConsumed());
Assert.assertFalse(wrapper.isRepeatable());
Mockito.verify(entity).writeTo(outstream);
}
}

View File

@ -0,0 +1,140 @@
/*
* ====================================================================
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.impl.client.builder;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketException;
import junit.framework.Assert;
import org.apache.http.HttpEntity;
import org.apache.http.util.EntityUtils;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
public class TestResponseEntityWrapper {
private InputStream instream;
private HttpEntity entity;
private ConnectionReleaseTriggerImpl releaseTrigger;
private ResponseEntityWrapper wrapper;
@Before
public void setup() throws Exception {
instream = Mockito.mock(InputStream.class);
entity = Mockito.mock(HttpEntity.class);;
Mockito.when(entity.getContent()).thenReturn(instream);
releaseTrigger = Mockito.mock(ConnectionReleaseTriggerImpl.class);
wrapper = new ResponseEntityWrapper(entity, releaseTrigger);
}
@Test
public void testReusableEntityStreamClosed() throws Exception {
Mockito.when(entity.isStreaming()).thenReturn(true);
Mockito.when(releaseTrigger.isReusable()).thenReturn(true);
EntityUtils.consume(wrapper);
Mockito.verify(instream, Mockito.times(1)).close();
Mockito.verify(releaseTrigger).releaseConnection();
}
@Test
public void testReusableEntityStreamClosedIOError() throws Exception {
Mockito.when(entity.isStreaming()).thenReturn(true);
Mockito.when(releaseTrigger.isReusable()).thenReturn(true);
Mockito.doThrow(new IOException()).when(instream).close();
try {
EntityUtils.consume(wrapper);
Assert.fail("IOException expected");
} catch (IOException ex) {
}
Mockito.verify(releaseTrigger).abortConnection();
}
@Test
public void testEntityStreamClosedIOErrorAlreadyReleased() throws Exception {
Mockito.when(entity.isStreaming()).thenReturn(true);
Mockito.when(releaseTrigger.isReusable()).thenReturn(true);
Mockito.when(releaseTrigger.isReleased()).thenReturn(true);
Mockito.doThrow(new SocketException()).when(instream).close();
EntityUtils.consume(wrapper);
Mockito.verify(releaseTrigger).abortConnection();
}
@Test
public void testReusableEntityWriteTo() throws Exception {
OutputStream outstream = Mockito.mock(OutputStream.class);
Mockito.when(entity.isStreaming()).thenReturn(true);
Mockito.when(releaseTrigger.isReusable()).thenReturn(true);
wrapper.writeTo(outstream);
Mockito.verify(releaseTrigger).releaseConnection();
}
@Test
public void testReusableEntityWriteToIOError() throws Exception {
OutputStream outstream = Mockito.mock(OutputStream.class);
Mockito.when(entity.isStreaming()).thenReturn(true);
Mockito.when(releaseTrigger.isReusable()).thenReturn(true);
Mockito.doThrow(new IOException()).when(entity).writeTo(outstream);
try {
wrapper.writeTo(outstream);
Assert.fail("IOException expected");
} catch (IOException ex) {
}
Mockito.verify(releaseTrigger, Mockito.never()).releaseConnection();
Mockito.verify(releaseTrigger).abortConnection();
}
@Test
public void testReusableEntityEndOfStream() throws Exception {
Mockito.when(instream.read()).thenReturn(-1);
Mockito.when(entity.isStreaming()).thenReturn(true);
Mockito.when(releaseTrigger.isReusable()).thenReturn(true);
InputStream content = wrapper.getContent();
Assert.assertEquals(-1, content.read());
Mockito.verify(instream).close();
Mockito.verify(releaseTrigger).releaseConnection();
}
@Test
public void testReusableEntityEndOfStreamIOError() throws Exception {
Mockito.when(instream.read()).thenReturn(-1);
Mockito.when(entity.isStreaming()).thenReturn(true);
Mockito.when(releaseTrigger.isReusable()).thenReturn(true);
Mockito.doThrow(new IOException()).when(instream).close();
InputStream content = wrapper.getContent();
try {
content.read();
Assert.fail("IOException expected");
} catch (IOException ex) {
}
Mockito.verify(releaseTrigger).abortConnection();
}
}

View File

@ -25,7 +25,7 @@
* *
*/ */
package org.apache.http.conn; package org.apache.http.impl.client.integration;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;