public void retryRecoverableErrors(boolean http10) throws Exception {
        logTestStart();
        String testURI = "http://kenai.com/jbosh/junit";
        BodyQName ref = BodyQName.createWithPrefix(testURI, "ref", "test");

        // Initiate a new session
        session.send(ComposableBody.builder().build());
        StubConnection conn = cm.awaitConnection();
        AbstractBody scr = this.getSessionCreationResponse(conn.getRequest().getBody())
                .setAttribute(Attributes.REQUESTS, "3")
                .build();
        if(http10)
            conn.forceHTTP1();
        conn.sendResponse(scr);
        session.drain();

        // Send a couple requests
        session.send(ComposableBody.builder()
                .setNamespaceDefinition("test", testURI)
                .setAttribute(ref, "Req1")
                .build());
        StubConnection conn1 = cm.awaitConnection();
        session.send(ComposableBody.builder()
                .setNamespaceDefinition("test", testURI)
                .setAttribute(ref, "Req2")
                .build());
        StubConnection conn2 = cm.awaitConnection();
        String expected2 = conn2.getRequest().getBody().toXML();

        // When testing HTTP/1.0, send a response to the second request before
        // returning an error on the first.  With pipelining enabled on HTTP/1.1,
        // this can't happen.
        if(http10) {
            conn2.sendResponse(ComposableBody.builder()
                    .setNamespaceDefinition("test", testURI)
                    .setAttribute(ref, "Resp2")
                    .build());
        }

        // When we send the response below, the requests will be resent.  Verify
        // from a listener that the retransmissions are sent in the correct order.
        final ArrayList<String> orderedResends = new ArrayList<String>();
        session.addBOSHClientRequestListener(new BOSHClientRequestListener() {
            public void requestSent(BOSHMessageEvent event) {
                synchronized(orderedResends) {
                    String actual = event.getBody().toXML();
                    orderedResends.add(actual);
                    orderedResends.notify();
                }
            }
        });

        // Now respond to the first request with a recoverable error
        String expected1 = conn1.getRequest().getBody().toXML();
        conn1.sendResponse(ComposableBody.builder()
                .setNamespaceDefinition("test", testURI)
                .setAttribute(Attributes.TYPE, "error")
                .setAttribute(ref, "Resp1")
                .build());

        // We should now receive requests which are duplicates of msg 1 and 2

        // Get msg 1 duplicate
        conn = cm.awaitConnection();
        String actual1 = conn.getRequest().getBody().toXML();
        conn.sendResponse(ComposableBody.builder()
                .setNamespaceDefinition("test", testURI)
                .setAttribute(ref, "Resp3")
                .build());

        // Get msg 2 duplicate
        conn = cm.awaitConnection();
        String actual2 = conn.getRequest().getBody().toXML();
        conn.sendResponse(ComposableBody.builder()
                .setNamespaceDefinition("test", testURI)
                .setAttribute(ref, "Resp4")
                .build());

        synchronized(orderedResends) {
            while(orderedResends.size() < 2) {
                orderedResends.wait();
            }
        }

        // Check that the resends were sent out in the correct order.
        assertEquals(expected1, orderedResends.get(0));
        assertEquals(expected2, orderedResends.get(1));

        // Check that the CM received the resends, in either order.  In order
        // to verify ordering here, we'd need to enable pipelining in StubCM,
        // so the resends aren't sent in separate connections.
        if(!(expected1.equals(actual1) && expected2.equals(actual2)) &&
           !(expected1.equals(actual2) && expected2.equals(actual1))) {
            fail("Expected:\n" + expected1 + "\nand\n" + expected2 +
                    "\nbut got:\n" + actual1 + "\nand\n" + actual2 + "\n");
        }

        session.drain();
    }