locust 2.29.2.dev34__py3-none-any.whl → 2.29.2.dev42__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. locust/_version.py +6 -2
  2. locust/contrib/fasthttp.py +1 -1
  3. locust/dispatch.py +7 -6
  4. {locust-2.29.2.dev34.dist-info → locust-2.29.2.dev42.dist-info}/METADATA +31 -26
  5. {locust-2.29.2.dev34.dist-info → locust-2.29.2.dev42.dist-info}/RECORD +16 -46
  6. locust-2.29.2.dev42.dist-info/WHEEL +4 -0
  7. locust-2.29.2.dev42.dist-info/entry_points.txt +3 -0
  8. locust/test/__init__.py +0 -15
  9. locust/test/fake_module1_for_env_test.py +0 -7
  10. locust/test/fake_module2_for_env_test.py +0 -7
  11. locust/test/mock_locustfile.py +0 -56
  12. locust/test/mock_logging.py +0 -28
  13. locust/test/test_debugging.py +0 -39
  14. locust/test/test_dispatch.py +0 -4170
  15. locust/test/test_env.py +0 -283
  16. locust/test/test_fasthttp.py +0 -785
  17. locust/test/test_http.py +0 -325
  18. locust/test/test_interruptable_task.py +0 -48
  19. locust/test/test_load_locustfile.py +0 -228
  20. locust/test/test_locust_class.py +0 -831
  21. locust/test/test_log.py +0 -237
  22. locust/test/test_main.py +0 -2264
  23. locust/test/test_old_wait_api.py +0 -0
  24. locust/test/test_parser.py +0 -450
  25. locust/test/test_runners.py +0 -4476
  26. locust/test/test_sequential_taskset.py +0 -157
  27. locust/test/test_stats.py +0 -866
  28. locust/test/test_tags.py +0 -440
  29. locust/test/test_taskratio.py +0 -94
  30. locust/test/test_users.py +0 -69
  31. locust/test/test_util.py +0 -33
  32. locust/test/test_wait_time.py +0 -79
  33. locust/test/test_web.py +0 -1257
  34. locust/test/test_zmqrpc.py +0 -58
  35. locust/test/testcases.py +0 -248
  36. locust/test/util.py +0 -88
  37. locust-2.29.2.dev34.dist-info/WHEEL +0 -5
  38. locust-2.29.2.dev34.dist-info/entry_points.txt +0 -2
  39. locust-2.29.2.dev34.dist-info/top_level.txt +0 -1
  40. {locust-2.29.2.dev34.dist-info → locust-2.29.2.dev42.dist-info}/LICENSE +0 -0
@@ -1,58 +0,0 @@
1
- from locust.exception import RPCError, RPCReceiveError, RPCSendError
2
- from locust.rpc import Message, zmqrpc
3
- from locust.test.testcases import LocustTestCase
4
-
5
- from time import sleep
6
-
7
- import zmq
8
-
9
-
10
- class ZMQRPC_tests(LocustTestCase):
11
- def setUp(self):
12
- super().setUp()
13
- self.server = zmqrpc.Server("*", 0)
14
- self.client = zmqrpc.Client("localhost", self.server.port, "identity")
15
-
16
- def tearDown(self):
17
- self.server.close()
18
- self.client.close()
19
- super().tearDown()
20
-
21
- def test_constructor(self):
22
- self.assertEqual(self.server.socket.getsockopt(zmq.TCP_KEEPALIVE), 1)
23
- self.assertEqual(self.server.socket.getsockopt(zmq.TCP_KEEPALIVE_IDLE), 30)
24
- self.assertEqual(self.server.socket.getsockopt(zmq.IPV6), 1)
25
- self.assertEqual(self.client.socket.getsockopt(zmq.TCP_KEEPALIVE), 1)
26
- self.assertEqual(self.client.socket.getsockopt(zmq.TCP_KEEPALIVE_IDLE), 30)
27
- self.assertEqual(self.client.socket.getsockopt(zmq.IPV6), 1)
28
-
29
- def test_client_send(self):
30
- self.client.send(Message("test", "message", "identity"))
31
- addr, msg = self.server.recv_from_client()
32
- self.assertEqual(addr, "identity")
33
- self.assertEqual(msg.type, "test")
34
- self.assertEqual(msg.data, "message")
35
-
36
- def test_client_recv(self):
37
- sleep(0.1)
38
- # We have to wait for the client to finish connecting
39
- # before sending a msg to it.
40
- self.server.send_to_client(Message("test", "message", "identity"))
41
- msg = self.client.recv()
42
- self.assertEqual(msg.type, "test")
43
- self.assertEqual(msg.data, "message")
44
- self.assertEqual(msg.node_id, "identity")
45
-
46
- def test_client_retry(self):
47
- server = zmqrpc.Server("*", 0)
48
- server.socket.close()
49
- with self.assertRaises(RPCError):
50
- server.recv_from_client()
51
-
52
- def test_rpc_error(self):
53
- server = zmqrpc.Server("*", 0)
54
- with self.assertRaises(RPCError):
55
- server = zmqrpc.Server("*", server.port)
56
- server.close()
57
- with self.assertRaises(RPCSendError):
58
- server.send_to_client(Message("test", "message", "identity"))
locust/test/testcases.py DELETED
@@ -1,248 +0,0 @@
1
- import locust
2
- from locust import log
3
- from locust.env import Environment
4
- from locust.event import Events
5
- from locust.test.mock_logging import MockedLoggingHandler
6
- from locust.test.util import clear_all_functools_lru_cache
7
-
8
- import base64
9
- import logging
10
- import random
11
- import sys
12
- import unittest
13
- import warnings
14
- from io import BytesIO
15
-
16
- import gevent
17
- import gevent.pywsgi
18
- from flask import Flask, Response, make_response, redirect, request, send_file, stream_with_context
19
-
20
- app = Flask(__name__)
21
- app.jinja_env.add_extension("jinja2.ext.do")
22
-
23
-
24
- @app.route("/ultra_fast")
25
- def ultra_fast():
26
- return "This is an ultra fast response"
27
-
28
-
29
- @app.route("/fast")
30
- def fast():
31
- gevent.sleep(random.choice([0.1, 0.2, 0.3]))
32
- return "This is a fast response"
33
-
34
-
35
- @app.route("/slow")
36
- def slow():
37
- if delay := request.args.get("delay"):
38
- gevent.sleep(float(delay))
39
- else:
40
- gevent.sleep(random.choice([0.5, 1, 1.5]))
41
- return "This is a slow response"
42
-
43
-
44
- @app.route("/consistent")
45
- def consistent():
46
- gevent.sleep(0.2)
47
- return "This is a consistent response"
48
-
49
-
50
- @app.route("/request_method", methods=["POST", "GET", "HEAD", "PUT", "DELETE", "PATCH"])
51
- def request_method():
52
- return request.method
53
-
54
-
55
- @app.route("/request_header_test")
56
- def request_header_test():
57
- x_header_test = request.headers["X-Header-Test"]
58
- response = Response(x_header_test)
59
- response.headers["X-Header-Test"] = x_header_test
60
-
61
- return response
62
-
63
-
64
- @app.route("/post", methods=["POST"])
65
- @app.route("/put", methods=["PUT"])
66
- def manipulate():
67
- return str(request.form.get("arg", ""))
68
-
69
-
70
- @app.route("/get_arg", methods=["GET"])
71
- def get_arg():
72
- return request.args.get("arg")
73
-
74
-
75
- @app.route("/fail")
76
- def failed_request():
77
- return "This response failed", 500
78
-
79
-
80
- @app.route("/status/204")
81
- def status_204():
82
- return "", 204
83
-
84
-
85
- @app.route("/redirect", methods=["GET", "POST"])
86
- def do_redirect():
87
- if delay := request.args.get("delay"):
88
- gevent.sleep(float(delay))
89
- url = request.args.get("url", "/ultra_fast")
90
- return redirect(url)
91
-
92
-
93
- @app.route("/basic_auth")
94
- def basic_auth():
95
- auth = base64.b64decode(request.headers.get("Authorization", "").replace("Basic ", "")).decode("utf-8")
96
- if auth == "locust:menace":
97
- return "Authorized"
98
- resp = make_response("401 Authorization Required", 401)
99
- resp.headers["WWW-Authenticate"] = 'Basic realm="Locust"'
100
- return resp
101
-
102
-
103
- @app.route("/no_content_length")
104
- def no_content_length():
105
- r = send_file(
106
- BytesIO(b"This response does not have content-length in the header"),
107
- etag=False,
108
- mimetype="text/plain",
109
- )
110
- r.headers.remove("Content-Length")
111
- return r
112
-
113
-
114
- @app.errorhandler(404)
115
- def not_found(error):
116
- return "Not Found", 404
117
-
118
-
119
- @app.route("/streaming/<int:iterations>")
120
- def streaming_response(iterations):
121
- import time
122
-
123
- def generate():
124
- yield "<html><body><h1>streaming response</h1>"
125
- for i in range(iterations):
126
- yield f"<span>{i}</span>\n"
127
- time.sleep(0.01)
128
- yield "</body></html>"
129
-
130
- return Response(stream_with_context(generate()), mimetype="text/html")
131
-
132
-
133
- @app.route("/set_cookie", methods=["POST"])
134
- def set_cookie():
135
- response = make_response("ok")
136
- response.set_cookie(request.args.get("name"), request.args.get("value"))
137
- return response
138
-
139
-
140
- @app.route("/get_cookie")
141
- def get_cookie():
142
- return make_response(request.cookies.get(request.args.get("name"), ""))
143
-
144
-
145
- @app.route("/rest", methods=["POST"])
146
- def rest():
147
- return request.json
148
-
149
-
150
- @app.route("/content_type_missing_charset")
151
- def content_type_missing_charset():
152
- resp = make_response("stuff")
153
- resp.headers["Content-Type"] = "Content-Type: application/json;"
154
- return resp
155
-
156
-
157
- @app.route("/content_type_regular")
158
- def content_type_regular():
159
- resp = make_response("stuff")
160
- resp.headers["Content-Type"] = "Content-Type: application/json; charset=utf-8;"
161
- return resp
162
-
163
-
164
- @app.route("/content_type_with_extra_stuff")
165
- def content_type_with_extra_stuff():
166
- resp = make_response("stuff")
167
- resp.headers["Content-Type"] = "Content-Type: application/json; charset=utf-8; api-version=3.0"
168
- return resp
169
-
170
-
171
- class LocustTestCase(unittest.TestCase):
172
- """
173
- Test case class that restores locust.events.EventHook listeners on tearDown, so that it is
174
- safe to register any custom event handlers within the test.
175
- """
176
-
177
- def setUp(self):
178
- # Prevent args passed to test runner from being passed to Locust
179
- del sys.argv[1:]
180
-
181
- locust.events = Events()
182
- self.environment = Environment(events=locust.events, catch_exceptions=False)
183
- self.runner = self.environment.create_local_runner()
184
-
185
- # When running the tests in Python 3 we get warnings about unclosed sockets.
186
- # This causes tests that depends on calls to sys.stderr to fail, so we'll
187
- # suppress those warnings. For more info see:
188
- # https://github.com/requests/requests/issues/1882
189
- warnings.filterwarnings(action="ignore", message="unclosed <socket object", category=ResourceWarning)
190
- warnings.filterwarnings(
191
- action="ignore", message="unclosed context <zmq.green.Context", category=ResourceWarning
192
- )
193
-
194
- # set up mocked logging handler
195
- self._logger_class = MockedLoggingHandler()
196
- self._logger_class.setLevel(logging.INFO)
197
- self._root_log_handlers = [h for h in logging.root.handlers]
198
- [logging.root.removeHandler(h) for h in logging.root.handlers]
199
- logging.root.addHandler(self._logger_class)
200
- logging.root.setLevel(logging.INFO)
201
- self.mocked_log = MockedLoggingHandler
202
-
203
- # set unhandled exception flag to False
204
- log.unhandled_greenlet_exception = False
205
-
206
- def tearDown(self):
207
- # restore logging class
208
- logging.root.removeHandler(self._logger_class)
209
- [logging.root.addHandler(h) for h in self._root_log_handlers]
210
- self.mocked_log.reset()
211
-
212
- clear_all_functools_lru_cache()
213
-
214
-
215
- class WebserverTestCase(LocustTestCase):
216
- """
217
- Test case class that sets up an HTTP server which can be used within the tests
218
- """
219
-
220
- def setUp(self):
221
- super().setUp()
222
-
223
- self.connections_count = 0
224
- self.requests_count = 0
225
-
226
- class CountingWSGIHandler(gevent.pywsgi.WSGIHandler):
227
- def handle(this):
228
- self.connections_count += 1
229
- super().handle()
230
-
231
- def log_request(this):
232
- self.requests_count += 1
233
- super().log_request()
234
-
235
- self._web_server = gevent.pywsgi.WSGIServer(
236
- ("127.0.0.1", 0),
237
- app,
238
- log=None,
239
- handler_class=CountingWSGIHandler,
240
- )
241
- gevent.spawn(lambda: self._web_server.serve_forever())
242
- gevent.sleep(0.01)
243
- self.port = self._web_server.server_port
244
-
245
- def tearDown(self):
246
- super().tearDown()
247
- self._web_server.stop_accepting()
248
- self._web_server.stop()
locust/test/util.py DELETED
@@ -1,88 +0,0 @@
1
- import datetime
2
- import functools
3
- import gc
4
- import os
5
- import socket
6
- import warnings
7
- from contextlib import contextmanager
8
- from tempfile import NamedTemporaryFile
9
-
10
- from cryptography import x509
11
- from cryptography.hazmat.backends import default_backend
12
- from cryptography.hazmat.primitives import hashes, serialization
13
- from cryptography.hazmat.primitives.asymmetric import rsa
14
- from cryptography.x509.oid import NameOID
15
-
16
-
17
- @contextmanager
18
- def temporary_file(content, suffix="_locustfile.py", dir=None):
19
- f = NamedTemporaryFile(suffix=suffix, delete=False, dir=dir)
20
- f.write(content.encode("utf-8"))
21
- f.close()
22
- try:
23
- yield f.name
24
- finally:
25
- if os.path.exists(f.name):
26
- os.remove(f.name)
27
-
28
-
29
- @contextmanager
30
- def patch_env(name: str, value: str):
31
- prev_value = os.getenv(name)
32
- os.environ[name] = value
33
- try:
34
- yield
35
- finally:
36
- if prev_value is None:
37
- del os.environ[name]
38
- else:
39
- os.environ[name] = prev_value
40
-
41
-
42
- def get_free_tcp_port():
43
- """
44
- Find an unused TCP port
45
- """
46
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
47
- s.bind(("127.0.0.1", 0))
48
- s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
49
- port = s.getsockname()[1]
50
- s.close()
51
- return port
52
-
53
-
54
- def create_tls_cert(hostname):
55
- """Generate a TLS cert and private key to serve over https"""
56
- key = rsa.generate_private_key(public_exponent=2**16 + 1, key_size=2048, backend=default_backend())
57
- name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, hostname)])
58
- now = datetime.datetime.now(tz=datetime.timezone.utc)
59
- cert = (
60
- x509.CertificateBuilder()
61
- .subject_name(name)
62
- .issuer_name(name)
63
- .public_key(key.public_key())
64
- .serial_number(1000)
65
- .not_valid_before(now)
66
- .not_valid_after(now + datetime.timedelta(days=10 * 365))
67
- .sign(key, hashes.SHA256(), default_backend())
68
- )
69
- cert_pem = cert.public_bytes(encoding=serialization.Encoding.PEM)
70
- key_pem = key.private_bytes(
71
- encoding=serialization.Encoding.PEM,
72
- format=serialization.PrivateFormat.TraditionalOpenSSL,
73
- encryption_algorithm=serialization.NoEncryption(),
74
- )
75
-
76
- return cert_pem, key_pem
77
-
78
-
79
- def clear_all_functools_lru_cache() -> None:
80
- # Clear all `functools.lru_cache` to ensure that no state are persisted from one test to another.
81
- # Taken from https://stackoverflow.com/a/50699209.
82
- with warnings.catch_warnings():
83
- warnings.simplefilter(action="ignore", category=ResourceWarning)
84
- gc.collect()
85
- wrappers = [a for a in gc.get_objects() if isinstance(a, functools._lru_cache_wrapper)]
86
- assert len(wrappers) > 0
87
- for wrapper in wrappers:
88
- wrapper.cache_clear()
@@ -1,5 +0,0 @@
1
- Wheel-Version: 1.0
2
- Generator: setuptools (70.2.0)
3
- Root-Is-Purelib: true
4
- Tag: py3-none-any
5
-
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- locust = locust.main:main
@@ -1 +0,0 @@
1
- locust