forked from tmccombs/tls-listener
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest_examples.py
executable file
·139 lines (111 loc) · 3.69 KB
/
test_examples.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/usr/bin/env python3
"""
This script is intended to test the examples in the `examples` folder.
"""
import signal
import socket
import ssl
import subprocess
import time
import unittest
from contextlib import contextmanager
from http.client import HTTPConnection
from os import path
from urllib.request import HTTPSHandler, build_opener
HOST = "localhost"
PORT = 3000
DOMAIN = "test.local"
EXAMPLE_DIR = path.dirname(__file__)
CA_FILE = path.join(EXAMPLE_DIR, "tls_config", "localcert.pem")
context = ssl.create_default_context(cafile=CA_FILE)
context.options = ssl.PROTOCOL_TLS_CLIENT
class ExampleHttpsConnection(HTTPConnection):
def connect(self):
super().connect()
self.sock = context.wrap_socket(self.sock, server_hostname=DOMAIN)
class ExampleHttpsHandler(HTTPSHandler):
def __init__(self, debuglevel=0):
super().__init__(debuglevel, context=context)
def https_open(self, req):
return self.do_open(ExampleHttpsConnection, req)
opener = build_opener(ExampleHttpsHandler)
@contextmanager
def tls_conn():
with socket.create_connection((HOST, PORT)) as sock:
with context.wrap_socket(sock, server_hostname=DOMAIN) as tls:
yield tls
tls.shutdown(socket.SHUT_RDWR)
def build_examples():
proc = subprocess.run(
[
"cargo",
"build",
"--examples",
"--features",
"rustls,rt,tokio/rt-multi-thread",
]
)
proc.check_returncode()
@contextmanager
def run_example(name):
proc = subprocess.Popen(
path.join(EXAMPLE_DIR, "..", "target", "debug", "examples", name),
)
try:
time.sleep(0.1) # wait for process to start up
yield proc
finally:
proc.terminate()
proc.wait() # avoid warning about process still running
class TestExamples(unittest.TestCase):
@classmethod
def setUpClass(cls):
build_examples()
def run_echo_test(self, conn):
r = conn.makefile("r")
w = conn.makefile("w")
w.write("hello\n")
w.write("world\n")
w.write("it's great\n")
w.flush()
for line in ["hello\n", "world\n", "it's great\n"]:
self.assertEqual(r.readline(), line)
w.write("goodbye\n")
w.flush()
self.assertEqual(r.readline(), "goodbye\n")
def echo_test(self):
with tls_conn() as tls:
self.run_echo_test(tls)
def http_test(self):
with opener.open(f"https://{HOST}:{PORT}") as resp:
self.assertEqual(resp.status, 200)
self.assertEqual(resp.read(), b"Hello, World!")
def bad_connection_test(self, proc):
with socket.create_connection((HOST, PORT)) as s:
s.send(b"bad data")
self.assertIsNone(proc.poll(), "Bad data shouldn't kill process")
def test_echo(self):
with run_example("echo") as r:
f"pid={r.pid}"
self.echo_test()
with tls_conn() as t:
r.send_signal(signal.SIGINT)
time.sleep(0.1)
self.assertIsNone(
r.poll(), "Process should wait for connections to end on ctrl-c"
)
self.run_echo_test(t)
r.wait(0.5) # process should finish shortly after connection finishes
def test_echo_threads(self):
with run_example("echo-threads"):
self.echo_test()
def test_http_stream(self):
with run_example("http-stream") as r:
self.http_test()
self.bad_connection_test(r)
def test_http_plain(self):
with run_example("http"):
self.http_test()
def test_axum(self):
with run_example("axum"):
self.http_test()