Package: poorconn
Poorconn is a Python package that simulates poor network conditions. It is suitable for testing purposes, for both
Python and non-Python projects.It is capable of simulating the following poor network conditions:Throttled network connections. (delay_before_sending,delay_before_sending_upon_acceptance)Servers that cut off connections immediately upon accepting them. (close_upon_acceptance)Connections that are initially slow, but become normal subsequently. (delay_before_sending_once,delay_before_sending_upon_acceptance_once)QuickstartInstall this package via$pipinstall'poorconn[full]'# or "pip install poorconn" if you don't need pytest supportCommand Line UsageThe following example starts a local HTTP server at port 8000 that hosts static files at the current working directory.
It always closes connections upon accepting them:$python-mpoorconn-Hlocalhost-p8000close_upon_acceptanceIn this command,python-mpoorconninvokes Poorconn’s command line entrypoint,-Hlocalhostspecifies
the hostname,-p8000specifies the port number, andclose_upon_acceptanceis asimulation commandthat
simulates a specific poor network conditions, which in this case is closing connections upon accepting them.After running the command above, connections from a client would establish but fail to communicate subsequently:$wget-t1http://127.0.0.1:8000Connecting to 127.0.0.1:8000... connected.
HTTP request sent, awaiting response... No data received.
Giving up.For another example, to start a local HTTP server that always throttle connections upon accepting them, simply replaceclose_upon_acceptanceabove withdelay_before_sending_upon_acceptance--t=1--length=1024:$python-mpoorconndelay_before_sending_upon_acceptance--t=1--length=1024Here,-Hlocalhost-p8000is omitted because it’s Poorconn’s default host and port settings. In this command,poorconn.delay_before_sending_upon_acceptancedelays roughly 1 seconds for every 1024 bytes sent. The connection
is now throttled:$wgethttp://127.0.0.1:8000Connecting to 127.0.0.1:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1609 (1.6K) [text/html]
Saving to: 'index.html'

index.html    1.57K   804 B/s    in 2.0s  <====== NOTE the time

'index.html' saved [1609/1609](Output above is abridged.)Runpython-mpoorconn-hto view the help message and see thepoorconn module API referencesfor a list of simulation functions (which share the same names with
simulation commands).Docker ImageYou can also run Poorconn as a command line tool using ourDocker imageby replacingpython-mpoorconnwithdocker run registry.gitlab.com/xuhdev/poorconn. For instance, the following achieves the same effect as the
second command line example above:$dockerrun-p8000:8000registry.gitlab.com/xuhdev/poorconndelay_before_sending_upon_acceptance--t=1--length=1024Usage in PythonRunning the following Python script achieves the same effects as the first command line example above:fromhttp.serverimportHTTPServer,SimpleHTTPRequestHandlerfrompoorconnimportclose_upon_acceptance,make_socket_patchable# Start a local HTTP server that always closes connections upon establishedwithHTTPServer(("localhost",8000),SimpleHTTPRequestHandler)ashttpd:httpd.socket=make_socket_patchable(httpd.socket)close_upon_acceptance(httpd.socket)httpd.serve_forever()The code snippet above is very similar to that runs a basic http server in Python, except that the socket objecthttpd.socketis patched bypoorconn.close_upon_acceptancebefore http server is running.For the second command line example above, simply replaceclose_upon_acceptance(s)above withdelay_before_sending_upon_acceptance(s, t=1, length=1024)and adjust
imports.Integration with PytestIf you usepytest, you can also take advantage of poorconn fixtures inpoorconn.pytest_plugin. The following
example gets you started with testing against a slow HTTP server:pytest_plugins=('poorconn',)frompathlibimportPathimporttimeimportrequestsimportpytest@pytest.mark.poorconn_http_server_config(t=2,length=1024)deftest_slow_http_server(poorconn_http_server,tmp_path):"Test GETing from a slow local http server that delays 2 seconds to send every 1024 bytes."(tmp_path/'index.txt').write_bytes(b'h'*1024)starting_time=time.time()# Replace the following line with the program you want to testcontent=requests.get(f'{poorconn_http_server.url}/index.txt').contentending_time=time.time()assertending_time-starting_time>2Bug Reports and Feature RequestsPlease open a ticket on theGitLab Issue Tracker.ContributingContributions are welcome! To get started, check outCONTRIBUTING.Copyright and LicenseUnless otherwise stated in the headers of some files, all files in this project are licensed under LGPLv3+:Copyright (C) 2020–2021 Hong Xu <hong@topbug.net>This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General
Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
later version.This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.You should have received a copy of the GNU Lesser General Public License along with this program. If not, see
<https://www.gnu.org/licenses/>.