Skip to content

Commit

Permalink
HTTP protocol tests
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewgodwin committed Nov 26, 2017
1 parent 0626f39 commit b72349d
Show file tree
Hide file tree
Showing 10 changed files with 661 additions and 481 deletions.
7 changes: 1 addition & 6 deletions daphne/http_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,7 @@ def process(self):
# Remove our HTTP reply channel association
logger.debug("Upgraded connection %s to WebSocket", self.client_addr)
# Resume the producer so we keep getting data, if it's available as a method
# 17.1 version
if hasattr(self.channel, "_networkProducer"):
self.channel._networkProducer.resumeProducing()
# 16.x version
elif hasattr(self.channel, "resumeProducing"):
self.channel.resumeProducing()
self.channel._networkProducer.resumeProducing()

This comment has been minimized.

Copy link
@carltongibson

carltongibson Oct 28, 2024

Member

Hey @andrewgodwin — you're never going to remember this I guess (and rightly so) but I don't suppose I can trick your grey cells into recall Why it was OK to remove the conditional check here?

We have a new report in #535 that AttributeError: 'HTTPChannel' object has no attribute '_networkProducer' in the latest twisted 24.10.

I will continue finding the update here. (Min version 18 I'm guessing.)

Thanks/Sorry 😔

This comment has been minimized.

Copy link
@andrewgodwin

andrewgodwin Oct 29, 2024

Author Member

I'm afraid I have absolutely no recollection of this one - my only guess would have been that Twisted 16.x was out of support at the time and so I dropped that side of the if!

This comment has been minimized.

Copy link
@carltongibson

carltongibson Oct 29, 2024

Member

Hey @andrewgodwin — thanks for the reply — no problem! (100% to be expected that you have no concrete recollection of this!)

AFAICS: The _networkProducer should be set unconditionally by twisted in connectionMade — so there's something else going on.

I'll comment that on the ticket.

Thanks! Have a great day!


# Boring old HTTP.
else:
Expand Down
28 changes: 19 additions & 9 deletions daphne/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@ def run(self):
reactor.addSystemEventTrigger("before", "shutdown", self.kill_all_applications)
reactor.run(installSignalHandlers=self.signal_handlers)

def stop(self):
"""
Force-stops the server.
"""
reactor.stop()

### Protocol handling

def add_protocol(self, protocol):
Expand Down Expand Up @@ -159,16 +165,20 @@ def application_checker(self):
if application_instance.done():
exception = application_instance.exception()
if exception:
logging.error(
"Exception inside application: {}\n{}{}".format(
exception,
"".join(traceback.format_tb(
exception.__traceback__,
)),
" {}".format(exception),
if isinstance(exception, KeyboardInterrupt):
# Protocol is asking the server to exit (likely during test)
self.stop()
else:
logging.error(
"Exception inside application: {}\n{}{}".format(
exception,
"".join(traceback.format_tb(
exception.__traceback__,
)),
" {}".format(exception),
)
)
)
protocol.handle_exception(exception)
protocol.handle_exception(exception)
try:
del self.application_instances[protocol]
except KeyError:
Expand Down
86 changes: 86 additions & 0 deletions daphne/test_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import msgpack
import os
import tempfile


class TestApplication:
"""
An application that receives one or more messages, sends a response,
and then quits the server. For testing.
"""

setup_storage = os.path.join(tempfile.gettempdir(), "setup.testio")
result_storage = os.path.join(tempfile.gettempdir(), "result.testio")

def __init__(self, scope):
self.scope = scope
self.messages = []

async def __call__(self, send, receive):
# Load setup info
setup = self.load_setup()
try:
for _ in range(setup["receive_messages"]):
self.messages.append(await receive())
for message in setup["response_messages"]:
await send(message)
finally:
self.save_result()

@classmethod
def save_setup(cls, response_messages, receive_messages=1):
"""
Stores setup information.
"""
with open(cls.setup_storage, "wb") as fh:
fh.write(msgpack.packb(
{
"response_messages": response_messages,
"receive_messages": receive_messages,
},
use_bin_type=True,
))

@classmethod
def load_setup(cls):
"""
Returns setup details.
"""
with open(cls.setup_storage, "rb") as fh:
return msgpack.unpackb(fh.read(), encoding="utf-8")

def save_result(self):
"""
Saves details of what happened to the result storage.
We could use pickle here, but that seems wrong, still, somehow.
"""
with open(self.result_storage, "wb") as fh:
fh.write(msgpack.packb(
{
"scope": self.scope,
"messages": self.messages,
},
use_bin_type=True,
))

@classmethod
def load_result(cls):
"""
Returns result details.
"""
with open(cls.result_storage, "rb") as fh:
return msgpack.unpackb(fh.read(), encoding="utf-8")

@classmethod
def clear_storage(cls):
"""
Clears storage files.
"""
try:
os.unlink(cls.setup_storage)
except OSError:
pass
try:
os.unlink(cls.result_storage)
except OSError:
pass
197 changes: 0 additions & 197 deletions daphne/tests/test_http_request.py

This file was deleted.

Loading

0 comments on commit b72349d

Please sign in to comment.