'L{TLSMemoryBIOProtocol.loseConnection} sends a TLS close alert and
shuts down the underlying connection cleanly on both sides, after
transmitting all buffered data.'

def test_loseConnectionAfterHandshake(self):

    class NotifyingProtocol(ConnectionLostNotifyingProtocol, ):
        def __init__(self, onConnectionLost):
            ConnectionLostNotifyingProtocol.__init__(self, onConnectionLost)
            self.data = []
        def dataReceived(self, data):
            self.data.append(data)
    clientConnectionLost = Deferred()
    clientFactory = ClientFactory()
    clientProtocol = NotifyingProtocol(clientConnectionLost)
    clientFactory.protocol = (lambda : clientProtocol)
    (clientContextFactory, handshakeDeferred) = HandshakeCallbackContextFactory.factoryAndDeferred()
    wrapperFactory = TLSMemoryBIOFactory(clientContextFactory, True, clientFactory)
    sslClientProtocol = wrapperFactory.buildProtocol(None)
    serverConnectionLost = Deferred()
    serverProtocol = NotifyingProtocol(serverConnectionLost)
    serverFactory = ServerFactory()
    serverFactory.protocol = (lambda : serverProtocol)
    serverContextFactory = ServerTLSContext()
    wrapperFactory = TLSMemoryBIOFactory(serverContextFactory, False, serverFactory)
    sslServerProtocol = wrapperFactory.buildProtocol(None)
    loopbackAsync(sslServerProtocol, sslClientProtocol)
    chunkOfBytes = ('123456890' * 100000)
    def cbHandshake(ignored):
        clientProtocol.transport.write(chunkOfBytes)
        serverProtocol.transport.write('x')
        serverProtocol.transport.loseConnection()
        return gatherResults([clientConnectionLost, serverConnectionLost])
    handshakeDeferred.addCallback(cbHandshake)
    def cbConnectionDone(result):
        (clientProtocol, serverProtocol) = result
        clientProtocol.lostConnectionReason.trap(ConnectionDone)
        serverProtocol.lostConnectionReason.trap(ConnectionDone)
        self.assertEqual(''.join(serverProtocol.data), chunkOfBytes)
        self.assertTrue(serverProtocol.transport.q.disconnect)
        self.assertTrue(clientProtocol.transport.q.disconnect)
    handshakeDeferred.addCallback(cbConnectionDone)
    return handshakeDeferred
