PageRenderTime 21ms CodeModel.GetById 1ms app.highlight 17ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/net/test_tcp.py

https://bitbucket.org/prologic/circuits/
Python | 259 lines | 200 code | 51 blank | 8 comment | 13 complexity | bef6cfea65aa28f52ea795746adbefaa MD5 | raw file
  1#!/usr/bin/env python
  2
  3import pytest
  4
  5import select
  6from socket import error as SocketError
  7from socket import EAI_NODATA, EAI_NONAME
  8from socket import socket, AF_INET, AF_INET6, SOCK_STREAM, has_ipv6
  9
 10from circuits import Manager, Debugger
 11from circuits.net.events import close, connect, write
 12from circuits.core.pollers import Select, Poll, EPoll, KQueue
 13from circuits.net.sockets import TCPServer, TCP6Server, TCPClient, TCP6Client
 14
 15from .client import Client
 16from .server import Server
 17from tests.conftest import WaitEvent
 18
 19
 20def wait_host(server):
 21    def checker(obj, attr):
 22        return all((getattr(obj, a) for a in attr))
 23    assert pytest.wait_for(server, ("host", "port"), checker)
 24
 25
 26def _pytest_generate_tests(metafunc, ipv6):
 27    metafunc.addcall(funcargs={"Poller": Select, "ipv6": ipv6})
 28
 29    if hasattr(select, "poll"):
 30        metafunc.addcall(funcargs={"Poller": Poll, "ipv6": ipv6})
 31
 32    if hasattr(select, "epoll"):
 33        metafunc.addcall(funcargs={"Poller": EPoll, "ipv6": ipv6})
 34
 35    if hasattr(select, "kqueue"):
 36        metafunc.addcall(funcargs={"Poller": KQueue, "ipv6": ipv6})
 37
 38
 39def pytest_generate_tests(metafunc):
 40    _pytest_generate_tests(metafunc, ipv6=False)
 41    if has_ipv6:
 42        _pytest_generate_tests(metafunc, ipv6=True)
 43
 44
 45def test_tcp_basic(Poller, ipv6):
 46    m = Manager() + Poller()
 47
 48    if ipv6:
 49        tcp_server = TCP6Server(("::1", 0))
 50        tcp_client = TCP6Client()
 51    else:
 52        tcp_server = TCPServer(0)
 53        tcp_client = TCPClient()
 54    server = Server() + tcp_server
 55    client = Client() + tcp_client
 56
 57    server.register(m)
 58    client.register(m)
 59
 60    m.start()
 61
 62    try:
 63        assert pytest.wait_for(client, "ready")
 64        assert pytest.wait_for(server, "ready")
 65        wait_host(server)
 66
 67        client.fire(connect(server.host, server.port))
 68        assert pytest.wait_for(client, "connected")
 69        assert pytest.wait_for(server, "connected")
 70        assert pytest.wait_for(client, "data", b"Ready")
 71
 72        client.fire(write(b"foo"))
 73        assert pytest.wait_for(server, "data", b"foo")
 74        assert pytest.wait_for(client, "data", b"foo")
 75
 76        client.fire(close())
 77        assert pytest.wait_for(client, "disconnected")
 78        assert pytest.wait_for(server, "disconnected")
 79
 80        server.fire(close())
 81        assert pytest.wait_for(server, "closed")
 82    finally:
 83        m.stop()
 84
 85
 86def test_tcp_reconnect(Poller, ipv6):
 87    ### XXX: Apparently this doesn't work on Windows either?
 88    ### XXX: UPDATE: Apparently Broken on Windows + Python 3.2
 89    ### TODO: Need to look into this. Find out why...
 90
 91    if pytest.PLATFORM == "win32" and pytest.PYVER[:2] >= (3, 2):
 92        pytest.skip("Broken on Windows on Python 3.2")
 93
 94    m = Manager() + Poller()
 95
 96    if ipv6:
 97        tcp_server = TCP6Server(("::1", 0))
 98        tcp_client = TCP6Client()
 99    else:
100        tcp_server = TCPServer(0)
101        tcp_client = TCPClient()
102    server = Server() + tcp_server
103    client = Client() + tcp_client
104
105    server.register(m)
106    client.register(m)
107
108    m.start()
109
110    try:
111        assert pytest.wait_for(client, "ready")
112        assert pytest.wait_for(server, "ready")
113        wait_host(server)
114
115        # 1st connect
116        client.fire(connect(server.host, server.port))
117        assert pytest.wait_for(client, "connected")
118        assert pytest.wait_for(server, "connected")
119        assert pytest.wait_for(client, "data", b"Ready")
120
121        client.fire(write(b"foo"))
122        assert pytest.wait_for(server, "data", b"foo")
123
124        # disconnect
125        client.fire(close())
126        assert pytest.wait_for(client, "disconnected")
127
128        # 2nd reconnect
129        client.fire(connect(server.host, server.port))
130        assert pytest.wait_for(client, "connected")
131        assert pytest.wait_for(server, "connected")
132        assert pytest.wait_for(client, "data", b"Ready")
133
134        client.fire(write(b"foo"))
135        assert pytest.wait_for(server, "data", b"foo")
136
137        client.fire(close())
138        assert pytest.wait_for(client, "disconnected")
139        assert pytest.wait_for(server, "disconnected")
140
141        server.fire(close())
142        assert pytest.wait_for(server, "closed")
143    finally:
144        m.stop()
145
146
147def test_tcp_connect_closed_port(Poller, ipv6):
148
149    if pytest.PLATFORM == "win32":
150        pytest.skip("Broken on Windows")
151
152    m = Manager() + Poller() + Debugger()
153
154    if ipv6:
155        tcp_server = TCP6Server(("::1", 0))
156        tcp_client = TCP6Client(connect_timeout=1)
157    else:
158        tcp_server = TCPServer(0)
159        tcp_client = TCPClient(connect_timeout=1)
160    server = Server() + tcp_server
161    client = Client() + tcp_client
162
163    server.register(m)
164    client.register(m)
165
166    m.start()
167
168    try:
169        assert pytest.wait_for(client, "ready")
170        assert pytest.wait_for(server, "ready")
171        wait_host(server)
172
173        host, port = server.host, server.port
174        tcp_server._sock.close()
175
176        # 1st connect
177        client.fire(connect(host, port))
178        waiter = WaitEvent(m, "unreachable", channel='client')
179        assert waiter.wait()
180    finally:
181        server.unregister()
182        client.unregister()
183        m.stop()
184
185
186def test_tcp_bind(Poller, ipv6):
187    m = Manager() + Poller()
188
189    if ipv6:
190        sock = socket(AF_INET6, SOCK_STREAM)
191        sock.bind(("::1", 0))
192        sock.listen(5)
193        _, bind_port, _, _ = sock.getsockname()
194        sock.close()
195        server = Server() + TCP6Server(("::1", 0))
196        client = Client() + TCP6Client()
197    else:
198        sock = socket(AF_INET, SOCK_STREAM)
199        sock.bind(("", 0))
200        sock.listen(5)
201        _, bind_port = sock.getsockname()
202        sock.close()
203        server = Server() + TCPServer(0)
204        client = Client() + TCPClient()
205
206    server.register(m)
207    client.register(m)
208
209    m.start()
210
211    try:
212        assert pytest.wait_for(client, "ready")
213        assert pytest.wait_for(server, "ready")
214        wait_host(server)
215
216        client.fire(connect(server.host, server.port))
217        assert pytest.wait_for(client, "connected")
218        assert pytest.wait_for(server, "connected")
219        assert pytest.wait_for(client, "data", b"Ready")
220
221        #assert server.client[1] == bind_port
222
223        client.fire(write(b"foo"))
224        assert pytest.wait_for(server, "data", b"foo")
225
226        client.fire(close())
227        assert pytest.wait_for(client, "disconnected")
228        assert pytest.wait_for(server, "disconnected")
229
230        server.fire(close())
231        assert pytest.wait_for(server, "closed")
232    finally:
233        m.stop()
234
235
236def test_tcp_lookup_failure(Poller, ipv6):
237    m = Manager() + Poller()
238
239    if ipv6:
240        tcp_client = TCP6Client()
241    else:
242        tcp_client = TCPClient()
243    client = Client() + tcp_client
244
245    client.register(m)
246
247    m.start()
248
249    try:
250        assert pytest.wait_for(client, "ready")
251
252        client.fire(connect("foo", 1234))
253        assert pytest.wait_for(client, "error", lambda obj, attr: isinstance(getattr(obj, attr), SocketError))
254        if pytest.PLATFORM == "win32":
255            assert client.error.errno == 11004
256        else:
257            assert client.error.errno in (EAI_NODATA, EAI_NONAME,)
258    finally:
259        m.stop()