@@ -0,0 +1,2515 @@
+package org.cometd.server;%0A%0Aimport java.util.concurrent.CountDownLatch;%0Aimport java.util.concurrent.TimeUnit;%0A%0Aimport org.cometd.bayeux.server.BayeuxServer;%0Aimport org.cometd.bayeux.server.ServerSession;%0Aimport org.eclipse.jetty.client.ContentExchange;%0Aimport org.eclipse.jetty.client.HttpExchange;%0Aimport org.eclipse.jetty.http.HttpHeaders;%0A%0Apublic class DisconnectTest extends AbstractBayeuxClientServerTest%0A%7B%0A    private BayeuxServer bayeux;%0A%0A    @Override%0A    protected void customizeBayeux(BayeuxServerImpl bayeux)%0A    %7B%0A        this.bayeux = bayeux;%0A    %7D%0A%0A    public void testDisconnect() throws Exception%0A    %7B%0A        ContentExchange handshake = newBayeuxExchange(%22%5B%7B%22 +%0A                %22%5C%22channel%5C%22: %5C%22/meta/handshake%5C%22,%22 +%0A                %22%5C%22version%5C%22: %5C%221.0%5C%22,%22 +%0A                %22%5C%22minimumVersion%5C%22: %5C%221.0%5C%22,%22 +%0A                %22%5C%22supportedConnectionTypes%5C%22: %5B%5C%22long-polling%5C%22%5D%22 +%0A                %22%7D%5D%22);%0A        httpClient.send(handshake);%0A        assertEquals(HttpExchange.STATUS_COMPLETED, handshake.waitForDone());%0A        assertEquals(200, handshake.getResponseStatus());%0A%0A        String clientId = extractClientId(handshake);%0A        String bayeuxCookie = extractBayeuxCookie(handshake);%0A%0A        ContentExchange connect = newBayeuxExchange(%22%5B%7B%22 +%0A                %22%5C%22channel%5C%22: %5C%22/meta/connect%5C%22,%22 +%0A                %22%5C%22clientId%5C%22: %5C%22%22 + clientId + %22%5C%22,%22 +%0A                %22%5C%22connectionType%5C%22: %5C%22long-polling%5C%22%22 +%0A                %22%7D%5D%22);%0A        connect.setRequestHeader(HttpHeaders.COOKIE, bayeuxCookie);%0A        httpClient.send(connect);%0A        assertEquals(HttpExchange.STATUS_COMPLETED, connect.waitForDone());%0A        assertEquals(200, connect.getResponseStatus());%0A%0A        ServerSession serverSession = bayeux.getSession(clientId);%0A        assertNotNull(serverSession);%0A%0A        final CountDownLatch latch = new CountDownLatch(1);%0A        serverSession.addListener(new ServerSession.RemoveListener()%0A        %7B%0A            public void removed(ServerSession session, boolean timeout)%0A            %7B%0A                latch.countDown();%0A            %7D%0A        %7D);%0A%0A        ContentExchange disconnect = newBayeuxExchange(%22%5B%7B%22 +%0A                %22%5C%22channel%5C%22: %5C%22/meta/disconnect%5C%22,%22 +%0A                %22%5C%22clientId%5C%22: %5C%22%22 + clientId + %22%5C%22%22 +%0A                %22%7D%5D%22);%0A        httpClient.send(disconnect);%0A        assertEquals(HttpExchange.STATUS_COMPLETED, disconnect.waitForDone());%0A        assertEquals(200, disconnect.getResponseStatus());%0A%0A        assertTrue(latch.await(1, TimeUnit.SECONDS));%0A    %7D%0A%7D%0A

Test for COMETD-226 (Client's cometd.disconnect() call does not trigger RemoveListener's removed() method immediately).