package dk.statsbiblioteket.util.rpc;

import junit.framework.TestCase;

/**
 * "Abstract" test suite to help test {@link ConnectionManager} implementations.
 */
public class ConnectionManagerTestCase extends TestCase {

    ConnectionManager<? extends TestIFace> cm;
    ConnectionFactory<? extends TestIFace> cf;
    String connId;

    public void tearDown () throws Exception {


        assertEquals("Connection leak detected", 0, getTotalRefCount(cm));
        cm.close();
    }

    public void testGetConnection () throws Exception {
        System.out.println ("TestGetConnection");

        ConnectionContext ctx = cm.get(connId);
        assertNotNull(ctx);
        
        TestIFace iface = (TestIFace) ctx.getConnection();
        assertNotNull(iface);

        assertEquals(connId, iface.ping());

        cm.release(ctx);
    }

    public void testBookkeeping () throws Exception {
        System.out.println ("TestBookKeeping");
        ConnectionContext ctx = cm.get(connId);

        assertEquals(1, cm.getConnections().size());
        assertEquals(1, ctx.getRefCount());

        cm.release (ctx);

        // Connection should still be cached, but refcount zero
        assertEquals(1, cm.getConnections().size());
        assertEquals(0, ctx.getRefCount());

        // Wait until connection is reaped. Connection should now be dropped
        // from the cache
        Thread.sleep ((cm.getLingerTime() + 1)*1000);
        assertEquals("All connections should be purged. "
                     + "Expecting connection count of 1",
                     0, cm.getConnections().size());
        assertEquals(0, ctx.getRefCount());
    }

    public void testMultiRef () throws Exception {
        System.out.println ("TestMultiRef");
        ConnectionContext ctx1 = cm.get(connId);

        assertEquals(1, cm.getConnections().size());
        assertEquals(1, ctx1.getRefCount());

        // Verify state if we allocate another connection handle
        ConnectionContext ctx2 = cm.get(connId);
        assertEquals(1, cm.getConnections().size());
        assertEquals(ctx1, ctx2); // Contexts on same connection should be shared
        assertEquals(2, ctx1.getRefCount());
        assertEquals(2, ctx2.getRefCount()); // Redundant since ctx1 == ctx2

        // Release first handle and check state
        cm.release (ctx1);
        assertEquals(1, cm.getConnections().size());
        assertEquals(1, ctx2.getRefCount());

        // Release second handle
        cm.release (ctx2);
        assertEquals(1, cm.getConnections().size()); // Connection not harvested yet
        assertEquals(0, ctx2.getRefCount());

        // Wait until connection is reaped. Connection should now be dropped
        // from the cache
        Thread.sleep ((cm.getLingerTime() + 1)*1000);
        assertEquals(0, cm.getConnections().size());
        assertEquals(0, ctx2.getRefCount());
    }

    public void testErrors () throws Exception {

        System.out.println ("TestErrors");
        ConnectionContext ctx1 = cm.get(connId);

        // Check that all is in order
        assertEquals(1, cm.getConnections().size());
        assertEquals(1, ctx1.getRefCount());

        // Claim that the connection is buggy, this should purge the ctx from the cache
        cm.reportError(ctx1, "Hey this connection is just totally b0rked! RLY!");
        assertEquals(0, cm.getConnections().size());

        // Get a new connection with same id
        ConnectionContext ctx2 = cm.get(connId);
        assertEquals(1, cm.getConnections().size());
        assertEquals(1, ctx2.getRefCount());
        assertTrue(ctx1 != ctx2);

        cm.release (ctx1);
        cm.release(ctx2);
        assertEquals(0, ctx1.getRefCount());
        assertEquals(0, ctx2.getRefCount());

    }

    public void testAllTests () throws Exception {

        testGetConnection();
        testBookkeeping();
        testMultiRef();
        testErrors();

        assertEquals(0, getTotalRefCount(cm));

        testClose();
    }

    public void testClose () throws Exception
    {
        System.out.println ("TestClose");
        ConnectionContext ctx = cm.get(connId);

        cm.release (ctx);
        cm.close();
    }

    public static int getTotalRefCount (ConnectionManager<?> cm) {
        int totalRefCount = 0;
        for (ConnectionContext<?> ctx : cm.getConnections()) {
            totalRefCount += ctx.getRefCount();
        }
        return totalRefCount;
    }

}

@@ -2805,32 +2805,148 @@
    assertEquals(
+%22All connections should be purged. %22%0A                     + %22Expecting connection count of 1%22,%0A                     
 0, cm.getConnect

Add assertion text at a place where we often appear to fail. Again :-)