#!/usr/bin/env python

# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed
# with this work for additional information regarding copyright
# ownership.  The ASF licenses this file to you under the Apache
# License, Version 2.0 (the "License"); you may not use this file
# except in compliance with the License.  You may obtain a copy of the
# License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.  See the License for the specific language governing
# permissions and limitations under the License.

# http://www.w3.org/Protocols/HTTP/AsImplemented
#
# The proxy crashes only after the response is complete.  It closes
# the client connection whether it crashes or not because an HTTP/0.9
# response is complete only after the origin closes its connection,
# and then the proxy normally does the same thing to the client
# connection (although it upgrades the response to HTTP/1.1).  So the
# only way to check that the proxy didn't crash is to open another
# connection.

from twisted.internet import error, protocol, reactor, tcp
from twisted.web import http

print '''1..1 http09
# The proxy doesn't crash on an HTTP/0.9 response'''


def callback():
    print 'not ok 1 - Why didn\'t the test finish yet?'

    reactor.stop()


reactor.callLater(2, callback)


class factory(protocol.Factory):
    class protocol(protocol.Protocol):
        def connectionMade(ctx):
            ctx.transport.write('http09\r\n')

            # The proxy crashes only after the response is complete
            ctx.transport.loseConnection()


origin = tcp.Port(0, factory())
origin.startListening()

print '# Listening on {0}:{1}'.format(*origin.socket.getsockname())


class factory(protocol.ClientFactory):
    def clientConnectionFailed(ctx, connector, reason):

        print 'Bail out!'
        reason.printTraceback()

        reactor.stop()

    class protocol(protocol.Protocol):
        def connectionLost(ctx, reason):

            # Open another connection
            class factory(protocol.ClientFactory):
                def clientConnectionFailed(ctx, connector, reason):
                    print 'not ok 1 - Did the proxy crash?  (Can\'t open another connection to it.)'

                    reactor.stop()

                class protocol(protocol.Protocol):
                    def connectionMade(ctx):
                        print 'ok 1 - The proxy didn\'t crash (opened another connection to it)'

                        reactor.stop()

            reactor.callLater(1, tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect)

        def connectionMade(ctx):
            ctx.transport.write('GET {0}:{1} HTTP/1.1\r\n\r\n'.format(*origin.socket.getsockname()))


tcp.Connector('localhost', 8080, factory(), 30, None, reactor).connect()

reactor.run()
