mirror of
https://github.com/apache/httpcomponents-client.git
synced 2025-02-27 13:25:35 +00:00
HTTPCLIENT-841: removed connection garbage collection due to a memory leak
git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@784361 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
29b8b170e4
commit
bd2f049ada
@ -1,6 +1,10 @@
|
|||||||
Changes since 4.0 beta 2
|
Changes since 4.0 beta 2
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
* [HTTPCLIENT-841] Removed automatic connection release using garbage collection
|
||||||
|
due to a memory leak
|
||||||
|
Contributed by Oleg Kalnichevski <olegk at apache.org>
|
||||||
|
|
||||||
* [HTTPCLIENT-853] Fixed bug causing invalid cookie origin port to be selected
|
* [HTTPCLIENT-853] Fixed bug causing invalid cookie origin port to be selected
|
||||||
when the target is accessed on the default port and the connection is
|
when the target is accessed on the default port and the connection is
|
||||||
established via a proxy.
|
established via a proxy.
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
import net.jcip.annotations.GuardedBy;
|
import net.jcip.annotations.GuardedBy;
|
||||||
import net.jcip.annotations.NotThreadSafe;
|
import net.jcip.annotations.ThreadSafe;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
@ -50,7 +50,6 @@
|
|||||||
import org.apache.http.conn.routing.HttpRoute;
|
import org.apache.http.conn.routing.HttpRoute;
|
||||||
import org.apache.http.impl.conn.IdleConnectionHandler;
|
import org.apache.http.impl.conn.IdleConnectionHandler;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract connection pool.
|
* An abstract connection pool.
|
||||||
* It is used by the {@link ThreadSafeClientConnManager}.
|
* It is used by the {@link ThreadSafeClientConnManager}.
|
||||||
@ -60,7 +59,9 @@
|
|||||||
*
|
*
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
@NotThreadSafe // unsynch access to refQueue, refWorker
|
|
||||||
|
@ThreadSafe
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public abstract class AbstractConnPool implements RefQueueHandler {
|
public abstract class AbstractConnPool implements RefQueueHandler {
|
||||||
|
|
||||||
private final Log log = LogFactory.getLog(getClass());
|
private final Log log = LogFactory.getLog(getClass());
|
||||||
@ -70,17 +71,12 @@ public abstract class AbstractConnPool implements RefQueueHandler {
|
|||||||
*/
|
*/
|
||||||
protected final Lock poolLock;
|
protected final Lock poolLock;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* References to issued connections.
|
* References to issued connections.
|
||||||
* Objects in this set are of class
|
|
||||||
* {@link BasicPoolEntryRef BasicPoolEntryRef},
|
|
||||||
* and point to the pool entry for the issued connection.
|
|
||||||
* GCed connections are detected by the missing pool entries.
|
|
||||||
* Must hold poolLock when accessing.
|
* Must hold poolLock when accessing.
|
||||||
*/
|
*/
|
||||||
@GuardedBy("poolLock")
|
@GuardedBy("poolLock")
|
||||||
protected Set<BasicPoolEntryRef> issuedConnections;
|
protected Set<BasicPoolEntry> leasedConnections;
|
||||||
|
|
||||||
/** The handler for idle connections. Must hold poolLock when accessing. */
|
/** The handler for idle connections. Must hold poolLock when accessing. */
|
||||||
@GuardedBy("poolLock")
|
@GuardedBy("poolLock")
|
||||||
@ -90,66 +86,32 @@ public abstract class AbstractConnPool implements RefQueueHandler {
|
|||||||
@GuardedBy("poolLock")
|
@GuardedBy("poolLock")
|
||||||
protected int numConnections;
|
protected int numConnections;
|
||||||
|
|
||||||
/**
|
|
||||||
* A reference queue to track loss of pool entries to GC.
|
|
||||||
* The same queue is used to track loss of the connection manager,
|
|
||||||
* so we cannot specialize the type.
|
|
||||||
*/
|
|
||||||
// TODO - this needs to be synchronized, e.g. on Pool Lock
|
|
||||||
protected ReferenceQueue<Object> refQueue;
|
|
||||||
|
|
||||||
/** A worker (thread) to track loss of pool entries to GC. */
|
|
||||||
// TODO - this needs to be synchronized, e.g. on Pool Lock
|
|
||||||
private RefQueueWorker refWorker;
|
|
||||||
|
|
||||||
|
|
||||||
/** Indicates whether this pool is shut down. */
|
/** Indicates whether this pool is shut down. */
|
||||||
protected volatile boolean isShutDown;
|
protected volatile boolean isShutDown;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
protected Set<BasicPoolEntryRef> issuedConnections;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
protected ReferenceQueue<Object> refQueue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new connection pool.
|
* Creates a new connection pool.
|
||||||
*/
|
*/
|
||||||
protected AbstractConnPool() {
|
protected AbstractConnPool() {
|
||||||
issuedConnections = new HashSet<BasicPoolEntryRef>();
|
leasedConnections = new HashSet<BasicPoolEntry>();
|
||||||
idleConnHandler = new IdleConnectionHandler();
|
idleConnHandler = new IdleConnectionHandler();
|
||||||
|
|
||||||
boolean fair = false; //@@@ check parameters to decide
|
boolean fair = false; //@@@ check parameters to decide
|
||||||
poolLock = new ReentrantLock(fair);
|
poolLock = new ReentrantLock(fair);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables connection garbage collection (GC).
|
* @deprecated do not sue
|
||||||
* This method must be called immediately after creating the
|
|
||||||
* connection pool. It is not possible to enable connection GC
|
|
||||||
* after pool entries have been created. Neither is it possible
|
|
||||||
* to disable connection GC.
|
|
||||||
*
|
|
||||||
* @throws IllegalStateException
|
|
||||||
* if connection GC is already enabled, or if it cannot be
|
|
||||||
* enabled because there already are pool entries
|
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public void enableConnectionGC()
|
public void enableConnectionGC()
|
||||||
throws IllegalStateException {
|
throws IllegalStateException {
|
||||||
|
|
||||||
if (refQueue != null) { // TODO - this access is not guaranteed protected by the pool lock
|
|
||||||
throw new IllegalStateException("Connection GC already enabled.");
|
|
||||||
}
|
|
||||||
poolLock.lock();
|
|
||||||
try {
|
|
||||||
if (numConnections > 0) { //@@@ is this check sufficient?
|
|
||||||
throw new IllegalStateException("Pool already in use.");
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
poolLock.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
refQueue = new ReferenceQueue<Object>();
|
|
||||||
refWorker = new RefQueueWorker(refQueue, this);
|
|
||||||
Thread t = new Thread(refWorker); //@@@ use a thread factory
|
|
||||||
t.setDaemon(true);
|
|
||||||
t.setName("RefQueueWorker@" + this);
|
|
||||||
t.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -200,45 +162,12 @@ BasicPoolEntry getEntry(
|
|||||||
public abstract void freeEntry(BasicPoolEntry entry, boolean reusable, long validDuration, TimeUnit timeUnit)
|
public abstract void freeEntry(BasicPoolEntry entry, boolean reusable, long validDuration, TimeUnit timeUnit)
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
|
||||||
// non-javadoc, see interface RefQueueHandler
|
|
||||||
public void handleReference(Reference<?> ref) {
|
public void handleReference(Reference<?> ref) {
|
||||||
|
|
||||||
poolLock.lock();
|
|
||||||
try {
|
|
||||||
|
|
||||||
if (ref instanceof BasicPoolEntryRef) {
|
|
||||||
// check if the GCed pool entry was still in use
|
|
||||||
//@@@ find a way to detect this without lookup
|
|
||||||
//@@@ flag in the BasicPoolEntryRef, to be reset when freed?
|
|
||||||
final boolean lost = issuedConnections.remove(ref);
|
|
||||||
if (lost) {
|
|
||||||
final HttpRoute route =
|
|
||||||
((BasicPoolEntryRef)ref).getRoute();
|
|
||||||
if (log.isDebugEnabled()) {
|
|
||||||
log.debug("Connection garbage collected. " + route);
|
|
||||||
}
|
|
||||||
handleLostEntry(route);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} finally {
|
@Deprecated
|
||||||
poolLock.unlock();
|
protected abstract void handleLostEntry(HttpRoute route);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles cleaning up for a lost pool entry with the given route.
|
|
||||||
* A lost pool entry corresponds to a connection that was
|
|
||||||
* garbage collected instead of being properly released.
|
|
||||||
*
|
|
||||||
* @param route the route of the pool entry that was lost
|
|
||||||
*/
|
|
||||||
protected abstract void handleLostEntry(HttpRoute route)
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes idle connections.
|
* Closes idle connections.
|
||||||
@ -291,23 +220,13 @@ public void shutdown() {
|
|||||||
if (isShutDown)
|
if (isShutDown)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// no point in monitoring GC anymore
|
|
||||||
if (refWorker != null)
|
|
||||||
refWorker.shutdown();
|
|
||||||
|
|
||||||
// close all connections that are issued to an application
|
// close all connections that are issued to an application
|
||||||
Iterator<BasicPoolEntryRef> iter = issuedConnections.iterator();
|
Iterator<BasicPoolEntry> iter = leasedConnections.iterator();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
BasicPoolEntryRef per = iter.next();
|
BasicPoolEntry entry = iter.next();
|
||||||
iter.remove();
|
iter.remove();
|
||||||
BasicPoolEntry entry = per.get();
|
|
||||||
if (entry != null) {
|
|
||||||
closeConnection(entry.getConnection());
|
closeConnection(entry.getConnection());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// remove all references to connections
|
|
||||||
//@@@ use this for shutting them down instead?
|
|
||||||
idleConnHandler.removeAll();
|
idleConnHandler.removeAll();
|
||||||
|
|
||||||
isShutDown = true;
|
isShutDown = true;
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
|
|
||||||
package org.apache.http.impl.conn.tsccm;
|
package org.apache.http.impl.conn.tsccm;
|
||||||
|
|
||||||
|
|
||||||
import java.lang.ref.ReferenceQueue;
|
import java.lang.ref.ReferenceQueue;
|
||||||
|
|
||||||
import org.apache.http.conn.OperatedClientConnection;
|
import org.apache.http.conn.OperatedClientConnection;
|
||||||
@ -38,8 +37,6 @@
|
|||||||
import org.apache.http.conn.routing.HttpRoute;
|
import org.apache.http.conn.routing.HttpRoute;
|
||||||
import org.apache.http.impl.conn.AbstractPoolEntry;
|
import org.apache.http.impl.conn.AbstractPoolEntry;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic implementation of a connection pool entry.
|
* Basic implementation of a connection pool entry.
|
||||||
*
|
*
|
||||||
@ -48,11 +45,17 @@
|
|||||||
public class BasicPoolEntry extends AbstractPoolEntry {
|
public class BasicPoolEntry extends AbstractPoolEntry {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A weak reference to <code>this</code> used to detect GC of entries.
|
* @deprecated do not use
|
||||||
* Pool entries can only be GCed when they are allocated by an application
|
|
||||||
* and therefore not referenced with a hard link in the manager.
|
|
||||||
*/
|
*/
|
||||||
private final BasicPoolEntryRef reference;
|
@Deprecated
|
||||||
|
public BasicPoolEntry(ClientConnectionOperator op,
|
||||||
|
HttpRoute route,
|
||||||
|
ReferenceQueue<Object> queue) {
|
||||||
|
super(op, route);
|
||||||
|
if (route == null) {
|
||||||
|
throw new IllegalArgumentException("HTTP route may not be null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new pool entry.
|
* Creates a new pool entry.
|
||||||
@ -63,13 +66,11 @@ public class BasicPoolEntry extends AbstractPoolEntry {
|
|||||||
* or <code>null</code>
|
* or <code>null</code>
|
||||||
*/
|
*/
|
||||||
public BasicPoolEntry(ClientConnectionOperator op,
|
public BasicPoolEntry(ClientConnectionOperator op,
|
||||||
HttpRoute route,
|
HttpRoute route) {
|
||||||
ReferenceQueue<Object> queue) {
|
|
||||||
super(op, route);
|
super(op, route);
|
||||||
if (route == null) {
|
if (route == null) {
|
||||||
throw new IllegalArgumentException("HTTP route may not be null");
|
throw new IllegalArgumentException("HTTP route may not be null");
|
||||||
}
|
}
|
||||||
this.reference = new BasicPoolEntryRef(this, queue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final OperatedClientConnection getConnection() {
|
protected final OperatedClientConnection getConnection() {
|
||||||
@ -80,8 +81,9 @@ protected final HttpRoute getPlannedRoute() {
|
|||||||
return super.route;
|
return super.route;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
protected final BasicPoolEntryRef getWeakRef() {
|
protected final BasicPoolEntryRef getWeakRef() {
|
||||||
return this.reference;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -89,6 +91,6 @@ protected void shutdownEntry() {
|
|||||||
super.shutdownEntry();
|
super.shutdownEntry();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // class BasicPoolEntry
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -283,7 +283,7 @@ protected BasicPoolEntry getEntryBlocking(
|
|||||||
|
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug("Total connections kept alive: " + freeConnections.size());
|
log.debug("Total connections kept alive: " + freeConnections.size());
|
||||||
log.debug("Total issued connections: " + issuedConnections.size());
|
log.debug("Total issued connections: " + leasedConnections.size());
|
||||||
log.debug("Total allocated connection: " + numConnections + " out of " + maxTotalConnections);
|
log.debug("Total allocated connection: " + numConnections + " out of " + maxTotalConnections);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -381,7 +381,7 @@ public void freeEntry(BasicPoolEntry entry, boolean reusable, long validDuration
|
|||||||
}
|
}
|
||||||
|
|
||||||
// no longer issued, we keep a hard reference now
|
// no longer issued, we keep a hard reference now
|
||||||
issuedConnections.remove(entry.getWeakRef());
|
leasedConnections.remove(entry);
|
||||||
|
|
||||||
RouteSpecificPool rospl = getRoutePool(route, true);
|
RouteSpecificPool rospl = getRoutePool(route, true);
|
||||||
|
|
||||||
@ -448,7 +448,7 @@ protected BasicPoolEntry getFreeEntry(RouteSpecificPool rospl, Object state) {
|
|||||||
rospl.dropEntry();
|
rospl.dropEntry();
|
||||||
numConnections--;
|
numConnections--;
|
||||||
} else {
|
} else {
|
||||||
issuedConnections.add(entry.getWeakRef());
|
leasedConnections.add(entry);
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,17 +486,13 @@ protected BasicPoolEntry createEntry(RouteSpecificPool rospl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// the entry will create the connection when needed
|
// the entry will create the connection when needed
|
||||||
BasicPoolEntry entry =
|
BasicPoolEntry entry = new BasicPoolEntry(op, rospl.getRoute());
|
||||||
new BasicPoolEntry(op, rospl.getRoute(), refQueue);
|
|
||||||
|
|
||||||
poolLock.lock();
|
poolLock.lock();
|
||||||
try {
|
try {
|
||||||
|
|
||||||
rospl.createdEntry(entry);
|
rospl.createdEntry(entry);
|
||||||
numConnections++;
|
numConnections++;
|
||||||
|
leasedConnections.add(entry);
|
||||||
issuedConnections.add(entry.getWeakRef());
|
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
poolLock.unlock();
|
poolLock.unlock();
|
||||||
}
|
}
|
||||||
|
@ -32,12 +32,12 @@
|
|||||||
|
|
||||||
import java.lang.ref.Reference;
|
import java.lang.ref.Reference;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback handler for {@link RefQueueWorker RefQueueWorker}.
|
* @deprecated do not use
|
||||||
*
|
*
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public interface RefQueueHandler {
|
public interface RefQueueHandler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,8 +42,9 @@
|
|||||||
* this worker. It will pick up the queued references and pass them
|
* this worker. It will pick up the queued references and pass them
|
||||||
* on to a handler for appropriate processing.
|
* on to a handler for appropriate processing.
|
||||||
*
|
*
|
||||||
* @since 4.0
|
* @deprecated do not use
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public class RefQueueWorker implements Runnable {
|
public class RefQueueWorker implements Runnable {
|
||||||
|
|
||||||
/** The reference queue to monitor. */
|
/** The reference queue to monitor. */
|
||||||
|
@ -123,13 +123,7 @@ protected void finalize() throws Throwable {
|
|||||||
* @return the connection pool to use
|
* @return the connection pool to use
|
||||||
*/
|
*/
|
||||||
protected AbstractConnPool createConnectionPool(final HttpParams params) {
|
protected AbstractConnPool createConnectionPool(final HttpParams params) {
|
||||||
|
return new ConnPoolByRoute(connOperator, params);
|
||||||
AbstractConnPool acp = new ConnPoolByRoute(connOperator, params);
|
|
||||||
boolean conngc = true; //@@@ check parameters to decide
|
|
||||||
if (conngc) {
|
|
||||||
acp.enableConnectionGC();
|
|
||||||
}
|
|
||||||
return acp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -492,65 +492,6 @@ public void testReleaseConnectionOnAbort() throws Exception {
|
|||||||
mgr.shutdown();
|
mgr.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests GC of an unreferenced connection.
|
|
||||||
*/
|
|
||||||
public void testConnectionGC() throws Exception {
|
|
||||||
// 3.x: TestHttpConnectionManager.testReclaimUnusedConnection
|
|
||||||
|
|
||||||
HttpParams mgrpar = defaultParams.copy();
|
|
||||||
ConnManagerParams.setMaxTotalConnections(mgrpar, 1);
|
|
||||||
|
|
||||||
ThreadSafeClientConnManager mgr = createTSCCM(mgrpar, null);
|
|
||||||
|
|
||||||
final HttpHost target = getServerHttp();
|
|
||||||
final HttpRoute route = new HttpRoute(target, null, false);
|
|
||||||
final int rsplen = 8;
|
|
||||||
final String uri = "/random/" + rsplen;
|
|
||||||
|
|
||||||
HttpRequest request =
|
|
||||||
new BasicHttpRequest("GET", uri, HttpVersion.HTTP_1_1);
|
|
||||||
|
|
||||||
ManagedClientConnection conn = getConnection(mgr, route);
|
|
||||||
conn.open(route, httpContext, defaultParams);
|
|
||||||
|
|
||||||
// a new context is created for each testcase, no need to reset
|
|
||||||
Helper.execute(request, conn, target,
|
|
||||||
httpExecutor, httpProcessor, defaultParams, httpContext);
|
|
||||||
|
|
||||||
// we leave the connection in mid-use
|
|
||||||
// it's not really re-usable, but it must be closed anyway
|
|
||||||
conn.markReusable();
|
|
||||||
|
|
||||||
// first check that we can't get another connection
|
|
||||||
try {
|
|
||||||
// this should fail quickly, connection has not been released
|
|
||||||
getConnection(mgr, route, 10L, TimeUnit.MILLISECONDS);
|
|
||||||
fail("ConnectionPoolTimeoutException should have been thrown");
|
|
||||||
} catch (ConnectionPoolTimeoutException e) {
|
|
||||||
// expected
|
|
||||||
}
|
|
||||||
|
|
||||||
// We now drop the hard references to the connection and trigger GC.
|
|
||||||
WeakReference<ManagedClientConnection> wref =
|
|
||||||
new WeakReference<ManagedClientConnection>(conn);
|
|
||||||
conn = null;
|
|
||||||
httpContext = null; // holds a reference to the connection
|
|
||||||
|
|
||||||
// Java does not guarantee that this will trigger the GC, but
|
|
||||||
// it does in the test environment. GC is asynchronous, so we
|
|
||||||
// need to give the garbage collector some time afterwards.
|
|
||||||
System.gc();
|
|
||||||
Thread.sleep(1000);
|
|
||||||
|
|
||||||
assertNull("connection not garbage collected", wref.get());
|
|
||||||
conn = getConnection(mgr, route, 10L, TimeUnit.MILLISECONDS);
|
|
||||||
assertFalse("GCed connection not closed", conn.isOpen());
|
|
||||||
|
|
||||||
mgr.shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests GC of an unreferenced connection manager.
|
* Tests GC of an unreferenced connection manager.
|
||||||
*/
|
*/
|
||||||
|
@ -1,137 +0,0 @@
|
|||||||
/*
|
|
||||||
* $HeadURL$
|
|
||||||
* $Revision$
|
|
||||||
* $Date$
|
|
||||||
* ====================================================================
|
|
||||||
* 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.conn.tsccm;
|
|
||||||
|
|
||||||
/*
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.concurrent.locks.Lock;
|
|
||||||
import java.util.concurrent.locks.Condition;
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
|
||||||
*/
|
|
||||||
|
|
||||||
import junit.framework.Test;
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
import junit.framework.TestSuite;
|
|
||||||
|
|
||||||
|
|
||||||
import org.apache.http.HttpHost;
|
|
||||||
import org.apache.http.conn.routing.HttpRoute;
|
|
||||||
import org.apache.http.conn.scheme.PlainSocketFactory;
|
|
||||||
import org.apache.http.conn.scheme.Scheme;
|
|
||||||
import org.apache.http.conn.scheme.SchemeRegistry;
|
|
||||||
import org.apache.http.conn.scheme.SocketFactory;
|
|
||||||
import org.apache.http.conn.ClientConnectionOperator;
|
|
||||||
import org.apache.http.impl.conn.DefaultClientConnectionOperator;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for simple helper classes without advanced functionality.
|
|
||||||
*/
|
|
||||||
public class TestDumbHelpers extends TestCase {
|
|
||||||
|
|
||||||
public final static
|
|
||||||
HttpHost TARGET = new HttpHost("target.test.invalid");
|
|
||||||
|
|
||||||
|
|
||||||
/** The default scheme registry. */
|
|
||||||
private SchemeRegistry supportedSchemes;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public TestDumbHelpers(String testName) {
|
|
||||||
super(testName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String args[]) {
|
|
||||||
String[] testCaseName = { TestDumbHelpers.class.getName() };
|
|
||||||
junit.textui.TestRunner.main(testCaseName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Test suite() {
|
|
||||||
return new TestSuite(TestDumbHelpers.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() {
|
|
||||||
supportedSchemes = new SchemeRegistry();
|
|
||||||
SocketFactory sf = PlainSocketFactory.getSocketFactory();
|
|
||||||
supportedSchemes.register(new Scheme("http", sf, 80));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void testBasicPoolEntry() {
|
|
||||||
HttpRoute route = new HttpRoute(TARGET);
|
|
||||||
ClientConnectionOperator ccop =
|
|
||||||
new DefaultClientConnectionOperator(supportedSchemes);
|
|
||||||
|
|
||||||
BasicPoolEntry bpe = null;
|
|
||||||
try {
|
|
||||||
bpe = new BasicPoolEntry(null, null, null);
|
|
||||||
fail("null operator not detected");
|
|
||||||
} catch (NullPointerException npx) {
|
|
||||||
// expected
|
|
||||||
} catch (IllegalArgumentException iax) {
|
|
||||||
// would be preferred
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
bpe = new BasicPoolEntry(ccop, null, null);
|
|
||||||
fail("null route not detected");
|
|
||||||
} catch (IllegalArgumentException iax) {
|
|
||||||
// expected
|
|
||||||
}
|
|
||||||
|
|
||||||
bpe = new BasicPoolEntry(ccop, route, null);
|
|
||||||
assertEquals ("wrong route", route, bpe.getPlannedRoute());
|
|
||||||
assertNotNull("missing ref", bpe.getWeakRef());
|
|
||||||
|
|
||||||
assertEquals("bad weak ref", bpe, bpe.getWeakRef().get());
|
|
||||||
assertEquals("bad ref route", route, bpe.getWeakRef().getRoute());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void testBasicPoolEntryRef() {
|
|
||||||
// the actual reference is tested implicitly with BasicPoolEntry
|
|
||||||
// but we need to cover the argument check in the constructor
|
|
||||||
try {
|
|
||||||
new BasicPoolEntryRef(null, null);
|
|
||||||
fail("null pool entry not detected");
|
|
||||||
} catch (IllegalArgumentException iax) {
|
|
||||||
// expected
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // class TestDumbHelpers
|
|
Loading…
x
Reference in New Issue
Block a user