def test_writeAfterShutdownWithoutReading(self):
        """
        A TCP transport which is written to after the connection has been shut
        down should notify its protocol that the connection has been lost, even
        if the TCP transport is not actively being monitored for read events
        (ie, pauseProducing was called on it).
        """
        # This is an unpleasant thing.  Generally tests shouldn't skip or
        # run based on the name of the reactor being used (most tests
        # shouldn't care _at all_ what reactor is being used, in fact).  The
        # IOCP reactor cannot pass this test, though -- please see the skip
        # reason below for details.
        if reactor.__class__.__name__ == 'IOCPReactor':
            raise unittest.SkipTest(
                "iocpreactor does not, in fact, stop reading immediately after "
                "pauseProducing is called. This results in a bonus disconnection "
                "notification. Under some circumstances, it might be possible to "
                "not receive this notifications (specifically, pauseProducing, "
                "deliver some data, proceed with this test).")

        # Called back after the protocol for the client side of the connection
        # has paused its transport, preventing it from reading, therefore
        # preventing it from noticing the disconnection before the rest of the
        # actions which are necessary to trigger the case this test is for have
        # been taken.
        clientPaused = defer.Deferred()

        # Called back when the protocol for the server side of the connection
        # has received connection lost notification.
        serverLost = defer.Deferred()

        class Disconnecter(protocol.Protocol):
            """
            Protocol for the server side of the connection which disconnects
            itself in a callback on clientPaused and publishes notification
            when its connection is actually lost.
            """
            def connectionMade(self):
                """
                Set up a callback on clientPaused to lose the connection.
                """
                msg('Disconnector.connectionMade')
                def disconnect(ignored):
                    msg('Disconnector.connectionMade disconnect')
                    self.transport.loseConnection()
                    msg('loseConnection called')
                clientPaused.addCallback(disconnect)

            def connectionLost(self, reason):
                """
                Notify observers that the server side of the connection has
                ended.
                """
                msg('Disconnecter.connectionLost')
                serverLost.callback(None)
                msg('serverLost called back')

        # Create the server port to which a connection will be made.
        server = protocol.ServerFactory()
        server.protocol = Disconnecter
        port = reactor.listenTCP(0, server, interface='127.0.0.1')
        self.addCleanup(port.stopListening)
        addr = port.getHost()

        @implementer(IPullProducer)
        class Infinite(object):
            """
            A producer which will write to its consumer as long as
            resumeProducing is called.

            @ivar consumer: The L{IConsumer} which will be written to.
            """

            def __init__(self, consumer):
                self.consumer = consumer

            def resumeProducing(self):
                msg('Infinite.resumeProducing')
                self.consumer.write(b'x')
                msg('Infinite.resumeProducing wrote to consumer')

            def stopProducing(self):
                msg('Infinite.stopProducing')


        class UnreadingWriter(protocol.Protocol):
            """
            Trivial protocol which pauses its transport immediately and then
            writes some bytes to it.
            """
            def connectionMade(self):
                msg('UnreadingWriter.connectionMade')
                self.transport.pauseProducing()
                clientPaused.callback(None)
                msg('clientPaused called back')
                def write(ignored):
                    msg('UnreadingWriter.connectionMade write')
                    # This needs to be enough bytes to spill over into the
                    # userspace Twisted send buffer - if it all fits into
                    # the kernel, Twisted won't even poll for OUT events,
                    # which means it won't poll for any events at all, so
                    # the disconnection is never noticed.  This is due to
                    # #1662.  When #1662 is fixed, this test will likely
                    # need to be adjusted, otherwise connection lost
                    # notification will happen too soon and the test will
                    # probably begin to fail with ConnectionDone instead of
                    # ConnectionLost (in any case, it will no longer be
                    # entirely correct).
                    producer = Infinite(self.transport)
                    msg('UnreadingWriter.connectionMade write created producer')
                    self.transport.registerProducer(producer, False)
                    msg('UnreadingWriter.connectionMade write registered producer')
                serverLost.addCallback(write)

        # Create the client and initiate the connection
        client = MyClientFactory()
        client.protocolFactory = UnreadingWriter
        clientConnectionLost = client.deferred
        def cbClientLost(ignored):
            msg('cbClientLost')
            return client.lostReason
        clientConnectionLost.addCallback(cbClientLost)
        msg('Connecting to %s:%s' % (addr.host, addr.port))
        reactor.connectTCP(addr.host, addr.port, client)

        # By the end of the test, the client should have received notification
        # of unclean disconnection.
        msg('Returning Deferred')
        return self.assertFailure(clientConnectionLost, error.ConnectionLost)

        A TCP transport which is written to after the connection has been shut
        down should notify its protocol that the connection has been lost, even
        if the TCP transport is not actively being monitored for read events
        (ie, pauseProducing was called on it).
        
stackoverflow/venv/lib/python3.6/site-packages/twisted/test/test_tcp.py