locust 2.20.1.dev28__py3-none-any.whl → 2.20.2__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.
- locust/__init__.py +7 -7
- locust/_version.py +2 -2
- locust/argument_parser.py +35 -18
- locust/clients.py +7 -6
- locust/contrib/fasthttp.py +42 -37
- locust/debug.py +14 -8
- locust/dispatch.py +25 -25
- locust/env.py +45 -37
- locust/event.py +13 -10
- locust/exception.py +0 -9
- locust/html.py +9 -8
- locust/input_events.py +7 -5
- locust/main.py +95 -47
- locust/rpc/protocol.py +4 -2
- locust/rpc/zmqrpc.py +6 -4
- locust/runners.py +69 -76
- locust/shape.py +7 -4
- locust/stats.py +73 -71
- locust/templates/index.html +8 -23
- locust/test/mock_logging.py +7 -5
- locust/test/test_debugging.py +4 -4
- locust/test/test_dispatch.py +10 -9
- locust/test/test_env.py +30 -1
- locust/test/test_fasthttp.py +9 -8
- locust/test/test_http.py +4 -3
- locust/test/test_interruptable_task.py +4 -4
- locust/test/test_load_locustfile.py +6 -5
- locust/test/test_locust_class.py +11 -5
- locust/test/test_log.py +5 -4
- locust/test/test_main.py +37 -7
- locust/test/test_parser.py +11 -15
- locust/test/test_runners.py +22 -21
- locust/test/test_sequential_taskset.py +3 -2
- locust/test/test_stats.py +16 -18
- locust/test/test_tags.py +3 -2
- locust/test/test_taskratio.py +3 -3
- locust/test/test_users.py +3 -3
- locust/test/test_util.py +3 -2
- locust/test/test_wait_time.py +3 -3
- locust/test/test_web.py +142 -27
- locust/test/test_zmqrpc.py +5 -3
- locust/test/testcases.py +7 -7
- locust/test/util.py +6 -7
- locust/user/__init__.py +1 -1
- locust/user/inspectuser.py +6 -5
- locust/user/sequential_taskset.py +3 -1
- locust/user/task.py +22 -27
- locust/user/users.py +17 -7
- locust/util/deprecation.py +0 -1
- locust/util/exception_handler.py +1 -1
- locust/util/load_locustfile.py +4 -2
- locust/web.py +102 -53
- locust/webui/dist/assets/auth-5e21717c.js.map +1 -0
- locust/webui/dist/assets/{index-01afe4fa.js → index-a83a5dd9.js} +85 -84
- locust/webui/dist/assets/index-a83a5dd9.js.map +1 -0
- locust/webui/dist/auth.html +20 -0
- locust/webui/dist/index.html +1 -1
- {locust-2.20.1.dev28.dist-info → locust-2.20.2.dist-info}/METADATA +2 -2
- locust-2.20.2.dist-info/RECORD +105 -0
- locust-2.20.1.dev28.dist-info/RECORD +0 -102
- {locust-2.20.1.dev28.dist-info → locust-2.20.2.dist-info}/LICENSE +0 -0
- {locust-2.20.1.dev28.dist-info → locust-2.20.2.dist-info}/WHEEL +0 -0
- {locust-2.20.1.dev28.dist-info → locust-2.20.2.dist-info}/entry_points.txt +0 -0
- {locust-2.20.1.dev28.dist-info → locust-2.20.2.dist-info}/top_level.txt +0 -0
@@ -1,11 +1,11 @@
|
|
1
|
-
from collections import defaultdict
|
2
|
-
from unittest import TestCase
|
3
|
-
from typing import DefaultDict
|
4
|
-
|
5
1
|
from locust import SequentialTaskSet, User, constant, task
|
6
2
|
from locust.env import Environment
|
7
3
|
from locust.exception import StopUser
|
8
4
|
|
5
|
+
from collections import defaultdict
|
6
|
+
from typing import DefaultDict
|
7
|
+
from unittest import TestCase
|
8
|
+
|
9
9
|
|
10
10
|
class InterruptableTaskSet(SequentialTaskSet):
|
11
11
|
counter: DefaultDict[str, int] = defaultdict(int)
|
@@ -1,12 +1,13 @@
|
|
1
|
-
import os
|
2
|
-
import textwrap
|
3
|
-
|
4
1
|
from locust import main
|
5
2
|
from locust.argument_parser import parse_options
|
6
3
|
from locust.main import create_environment
|
7
|
-
from locust.user import HttpUser,
|
4
|
+
from locust.user import HttpUser, TaskSet, User
|
8
5
|
from locust.util.load_locustfile import is_user_class
|
9
|
-
|
6
|
+
|
7
|
+
import os
|
8
|
+
import textwrap
|
9
|
+
|
10
|
+
from .mock_locustfile import MOCK_LOCUSTFILE_CONTENT, mock_locustfile
|
10
11
|
from .testcases import LocustTestCase
|
11
12
|
from .util import temporary_file
|
12
13
|
|
locust/test/test_locust_class.py
CHANGED
@@ -1,12 +1,18 @@
|
|
1
|
+
from locust import HttpUser, TaskSet, User, constant, task
|
2
|
+
from locust.env import Environment
|
3
|
+
from locust.exception import (
|
4
|
+
CatchResponseError,
|
5
|
+
InterruptTaskSet,
|
6
|
+
RescheduleTask,
|
7
|
+
RescheduleTaskImmediately,
|
8
|
+
ResponseError,
|
9
|
+
StopUser,
|
10
|
+
)
|
11
|
+
|
1
12
|
import gevent
|
2
13
|
from gevent import sleep
|
3
14
|
from gevent.pool import Group
|
4
15
|
|
5
|
-
from locust.exception import InterruptTaskSet, ResponseError
|
6
|
-
from locust import HttpUser, User, TaskSet, task, constant
|
7
|
-
from locust.env import Environment
|
8
|
-
from locust.exception import CatchResponseError, RescheduleTask, RescheduleTaskImmediately, StopUser
|
9
|
-
|
10
16
|
from .testcases import LocustTestCase, WebserverTestCase
|
11
17
|
|
12
18
|
|
locust/test/test_log.py
CHANGED
@@ -1,16 +1,17 @@
|
|
1
|
-
from
|
1
|
+
from locust import log
|
2
|
+
from locust.log import greenlet_exception_logger
|
3
|
+
|
2
4
|
import socket
|
3
5
|
import subprocess
|
4
6
|
import textwrap
|
5
7
|
from logging import getLogger
|
8
|
+
from unittest import mock
|
6
9
|
|
7
10
|
import gevent
|
8
11
|
|
9
|
-
from
|
10
|
-
from locust.log import greenlet_exception_logger
|
12
|
+
from . import changed_rlimit
|
11
13
|
from .testcases import LocustTestCase
|
12
14
|
from .util import temporary_file
|
13
|
-
from . import changed_rlimit
|
14
15
|
|
15
16
|
|
16
17
|
class TestGreenletExceptionLogger(LocustTestCase):
|
locust/test/test_main.py
CHANGED
@@ -2,23 +2,24 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
import json
|
4
4
|
import os
|
5
|
-
import sys
|
6
5
|
import platform
|
7
|
-
import unittest
|
8
|
-
import socket
|
9
|
-
import psutil
|
10
6
|
import pty
|
11
7
|
import signal
|
8
|
+
import socket
|
12
9
|
import subprocess
|
10
|
+
import sys
|
13
11
|
import textwrap
|
12
|
+
import unittest
|
13
|
+
from subprocess import DEVNULL, PIPE, STDOUT
|
14
14
|
from tempfile import TemporaryDirectory
|
15
15
|
from unittest import TestCase
|
16
|
-
|
16
|
+
|
17
17
|
import gevent
|
18
|
+
import psutil
|
18
19
|
import requests
|
19
20
|
|
20
|
-
from .mock_locustfile import
|
21
|
-
from .util import
|
21
|
+
from .mock_locustfile import MOCK_LOCUSTFILE_CONTENT, mock_locustfile
|
22
|
+
from .util import get_free_tcp_port, patch_env, temporary_file
|
22
23
|
|
23
24
|
|
24
25
|
def is_port_in_use(port: int) -> bool:
|
@@ -233,6 +234,35 @@ class StandaloneIntegrationTests(ProcessIntegrationTest):
|
|
233
234
|
stdout, stderr = proc.communicate()
|
234
235
|
self.assertIn("Starting web interface at", stderr)
|
235
236
|
|
237
|
+
def test_percentiles_to_statistics(self):
|
238
|
+
port = get_free_tcp_port()
|
239
|
+
with temporary_file(
|
240
|
+
content=textwrap.dedent(
|
241
|
+
"""
|
242
|
+
from locust import User, task, constant, events
|
243
|
+
from locust.stats import PERCENTILES_TO_STATISTICS
|
244
|
+
PERCENTILES_TO_STATISTICS = [0.9, 0.99]
|
245
|
+
class TestUser(User):
|
246
|
+
wait_time = constant(3)
|
247
|
+
@task
|
248
|
+
def my_task(self):
|
249
|
+
print("running my_task()")
|
250
|
+
"""
|
251
|
+
)
|
252
|
+
) as file_path:
|
253
|
+
proc = subprocess.Popen(
|
254
|
+
["locust", "-f", file_path, "--web-port", str(port), "--autostart", "--modern-ui"],
|
255
|
+
stdout=PIPE,
|
256
|
+
stderr=PIPE,
|
257
|
+
text=True,
|
258
|
+
)
|
259
|
+
gevent.sleep(1)
|
260
|
+
response = requests.get(f"http://localhost:{port}/")
|
261
|
+
self.assertEqual(200, response.status_code)
|
262
|
+
proc.send_signal(signal.SIGTERM)
|
263
|
+
stdout, stderr = proc.communicate()
|
264
|
+
self.assertIn("Starting web interface at", stderr)
|
265
|
+
|
236
266
|
def test_invalid_percentile_parameter(self):
|
237
267
|
with temporary_file(
|
238
268
|
content=textwrap.dedent(
|
locust/test/test_parser.py
CHANGED
@@ -1,19 +1,20 @@
|
|
1
|
-
import unittest
|
2
|
-
import os
|
3
|
-
from tempfile import NamedTemporaryFile, TemporaryDirectory
|
4
|
-
from random import randint
|
5
|
-
from unittest import mock
|
6
|
-
from io import StringIO
|
7
|
-
|
8
1
|
import locust
|
9
2
|
from locust.argument_parser import (
|
10
|
-
|
11
|
-
parse_options,
|
3
|
+
find_locustfiles,
|
12
4
|
get_parser,
|
5
|
+
locustfile_is_directory,
|
13
6
|
parse_locustfile_option,
|
7
|
+
parse_options,
|
14
8
|
ui_extra_args_dict,
|
15
|
-
find_locustfiles,
|
16
9
|
)
|
10
|
+
|
11
|
+
import os
|
12
|
+
import unittest
|
13
|
+
from io import StringIO
|
14
|
+
from random import randint
|
15
|
+
from tempfile import NamedTemporaryFile, TemporaryDirectory
|
16
|
+
from unittest import mock
|
17
|
+
|
17
18
|
from .mock_locustfile import mock_locustfile
|
18
19
|
from .testcases import LocustTestCase
|
19
20
|
|
@@ -49,11 +50,6 @@ class TestParser(unittest.TestCase):
|
|
49
50
|
self.assertEqual(options.locustfile, "locustfile_from_env")
|
50
51
|
self.assertEqual(options.host, "host_from_args") # overridden
|
51
52
|
|
52
|
-
def test_web_auth(self):
|
53
|
-
args = ["--web-auth", "hello:bye"]
|
54
|
-
opts = self.parser.parse_args(args)
|
55
|
-
self.assertEqual(opts.web_auth, "hello:bye")
|
56
|
-
|
57
53
|
|
58
54
|
class TestArgumentParser(LocustTestCase):
|
59
55
|
def setUp(self):
|
locust/test/test_runners.py
CHANGED
@@ -1,48 +1,49 @@
|
|
1
|
-
import json
|
2
|
-
import random
|
3
|
-
import time
|
4
|
-
import unittest
|
5
|
-
from collections import defaultdict
|
6
|
-
from operator import itemgetter
|
7
|
-
|
8
|
-
import gevent
|
9
|
-
from unittest import mock
|
10
|
-
import requests
|
11
|
-
from gevent import sleep
|
12
|
-
from gevent.pool import Group
|
13
|
-
from gevent.queue import Queue
|
14
|
-
|
15
1
|
import locust
|
16
2
|
from locust import (
|
17
3
|
LoadTestShape,
|
4
|
+
__version__,
|
18
5
|
constant,
|
19
6
|
runners,
|
20
|
-
__version__,
|
21
7
|
)
|
22
8
|
from locust.argument_parser import parse_options
|
23
9
|
from locust.env import Environment
|
24
|
-
from locust.exception import RPCError,
|
10
|
+
from locust.exception import RPCError, RPCReceiveError, StopUser
|
25
11
|
from locust.main import create_environment
|
26
12
|
from locust.rpc import Message
|
27
13
|
from locust.runners import (
|
28
|
-
LocalRunner,
|
29
14
|
STATE_INIT,
|
30
|
-
STATE_SPAWNING,
|
31
|
-
STATE_RUNNING,
|
32
15
|
STATE_MISSING,
|
33
|
-
|
16
|
+
STATE_RUNNING,
|
17
|
+
STATE_SPAWNING,
|
34
18
|
STATE_STOPPED,
|
19
|
+
STATE_STOPPING,
|
20
|
+
LocalRunner,
|
35
21
|
WorkerNode,
|
36
22
|
WorkerRunner,
|
37
23
|
)
|
38
24
|
from locust.stats import RequestStats
|
39
|
-
from .testcases import LocustTestCase
|
40
25
|
from locust.user import (
|
41
26
|
TaskSet,
|
42
27
|
User,
|
43
28
|
task,
|
44
29
|
)
|
30
|
+
|
31
|
+
import json
|
32
|
+
import random
|
33
|
+
import time
|
34
|
+
import unittest
|
35
|
+
from collections import defaultdict
|
36
|
+
from operator import itemgetter
|
37
|
+
from unittest import mock
|
38
|
+
|
39
|
+
import gevent
|
40
|
+
import requests
|
41
|
+
from gevent import sleep
|
42
|
+
from gevent.pool import Group
|
43
|
+
from gevent.queue import Queue
|
45
44
|
from retry import retry # type: ignore
|
45
|
+
|
46
|
+
from .testcases import LocustTestCase
|
46
47
|
from .util import patch_env
|
47
48
|
|
48
49
|
NETWORK_BROKEN = "network broken"
|
@@ -1,6 +1,7 @@
|
|
1
|
-
from locust import User,
|
2
|
-
from locust.user.sequential_taskset import SequentialTaskSet
|
1
|
+
from locust import User, constant, task
|
3
2
|
from locust.exception import RescheduleTask
|
3
|
+
from locust.user.sequential_taskset import SequentialTaskSet
|
4
|
+
|
4
5
|
from .testcases import LocustTestCase
|
5
6
|
|
6
7
|
|
locust/test/test_stats.py
CHANGED
@@ -1,33 +1,31 @@
|
|
1
|
-
import csv
|
2
|
-
import time
|
3
|
-
import unittest
|
4
|
-
import re
|
5
|
-
import os
|
6
|
-
import json
|
7
|
-
|
8
|
-
import gevent
|
9
|
-
from unittest import mock
|
10
1
|
import locust
|
11
|
-
from locust import HttpUser, TaskSet,
|
2
|
+
from locust import HttpUser, TaskSet, User, __version__, constant, task
|
12
3
|
from locust.env import Environment
|
13
4
|
from locust.rpc.protocol import Message
|
14
5
|
from locust.stats import (
|
6
|
+
PERCENTILES_TO_REPORT,
|
7
|
+
STATS_NAME_WIDTH,
|
8
|
+
STATS_TYPE_WIDTH,
|
15
9
|
CachedResponseTimes,
|
16
10
|
RequestStats,
|
11
|
+
StatsCSVFileWriter,
|
17
12
|
StatsEntry,
|
18
13
|
diff_response_time_dicts,
|
19
|
-
|
20
|
-
STATS_NAME_WIDTH,
|
21
|
-
STATS_TYPE_WIDTH,
|
14
|
+
stats_history,
|
22
15
|
)
|
23
|
-
from locust.
|
24
|
-
from locust.
|
25
|
-
from locust.test.testcases import LocustTestCase
|
16
|
+
from locust.test.test_runners import mocked_rpc
|
17
|
+
from locust.test.testcases import LocustTestCase, WebserverTestCase
|
26
18
|
from locust.user.inspectuser import _get_task_ratio
|
27
19
|
|
28
|
-
|
29
|
-
|
20
|
+
import csv
|
21
|
+
import json
|
22
|
+
import os
|
23
|
+
import re
|
24
|
+
import time
|
25
|
+
import unittest
|
26
|
+
from unittest import mock
|
30
27
|
|
28
|
+
import gevent
|
31
29
|
|
32
30
|
_TEST_CSV_STATS_INTERVAL_SEC = 0.2
|
33
31
|
_TEST_CSV_STATS_INTERVAL_WAIT_SEC = _TEST_CSV_STATS_INTERVAL_SEC + 0.1
|
locust/test/test_tags.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
-
from locust import TaskSet, User,
|
2
|
-
from locust.user.task import filter_tasks_by_tags
|
1
|
+
from locust import TaskSet, User, tag, task
|
3
2
|
from locust.env import Environment
|
3
|
+
from locust.user.task import filter_tasks_by_tags
|
4
|
+
|
4
5
|
from .testcases import LocustTestCase
|
5
6
|
|
6
7
|
|
locust/test/test_taskratio.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
import
|
1
|
+
from locust.user import TaskSet, User, task
|
2
|
+
from locust.user.inspectuser import _get_task_ratio, get_ratio
|
2
3
|
|
3
|
-
|
4
|
-
from locust.user.inspectuser import get_ratio, _get_task_ratio
|
4
|
+
import unittest
|
5
5
|
|
6
6
|
|
7
7
|
class TestTaskRatio(unittest.TestCase):
|
locust/test/test_users.py
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
+
from locust import HttpUser, User
|
2
|
+
from locust.test.testcases import WebserverTestCase
|
3
|
+
|
1
4
|
import unittest
|
2
5
|
|
3
6
|
from urllib3 import PoolManager
|
4
7
|
|
5
|
-
from locust import User, HttpUser
|
6
|
-
from locust.test.testcases import WebserverTestCase
|
7
|
-
|
8
8
|
|
9
9
|
class TestUserClass(unittest.TestCase):
|
10
10
|
class MyClassScopedUser(User):
|
locust/test/test_util.py
CHANGED
locust/test/test_wait_time.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
+
from locust import TaskSet, User, between, constant, constant_throughput
|
2
|
+
from locust.exception import MissingWaitTimeError
|
3
|
+
|
1
4
|
import random
|
2
5
|
import time
|
3
6
|
|
4
|
-
from locust import User, TaskSet, between, constant, constant_throughput
|
5
|
-
from locust.exception import MissingWaitTimeError
|
6
|
-
|
7
7
|
from .testcases import LocustTestCase
|
8
8
|
|
9
9
|
|
locust/test/test_web.py
CHANGED
@@ -1,32 +1,35 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import locust
|
4
|
+
from locust import LoadTestShape, constant, stats
|
5
|
+
from locust.argument_parser import get_parser, parse_options
|
6
|
+
from locust.env import Environment
|
7
|
+
from locust.log import LogReader
|
8
|
+
from locust.runners import Runner
|
9
|
+
from locust.stats import StatsCSVFileWriter
|
10
|
+
from locust.user import User, task
|
11
|
+
from locust.web import WebUI
|
12
|
+
|
1
13
|
import copy
|
2
14
|
import csv
|
3
15
|
import json
|
16
|
+
import logging
|
4
17
|
import os
|
5
18
|
import re
|
6
19
|
import textwrap
|
7
20
|
import traceback
|
8
|
-
import logging
|
9
21
|
from io import StringIO
|
10
22
|
from tempfile import NamedTemporaryFile, TemporaryDirectory
|
11
23
|
|
12
24
|
import gevent
|
13
25
|
import requests
|
26
|
+
from flask_login import UserMixin
|
14
27
|
from pyquery import PyQuery as pq
|
15
|
-
import locust
|
16
|
-
from locust import constant, LoadTestShape
|
17
|
-
from locust.argument_parser import get_parser, parse_options
|
18
|
-
from locust.user import User, task
|
19
|
-
from locust.env import Environment
|
20
|
-
from locust.runners import Runner
|
21
|
-
from locust import stats
|
22
|
-
from locust.stats import StatsCSVFileWriter
|
23
|
-
from locust.web import WebUI
|
24
|
-
from locust.log import LogReader
|
25
28
|
|
29
|
+
from ..util.load_locustfile import load_locustfile
|
26
30
|
from .mock_locustfile import mock_locustfile
|
27
31
|
from .testcases import LocustTestCase
|
28
32
|
from .util import create_tls_cert
|
29
|
-
from ..util.load_locustfile import load_locustfile
|
30
33
|
|
31
34
|
|
32
35
|
class _HeaderCheckMixin:
|
@@ -656,6 +659,41 @@ class TestWebUI(LocustTestCase, _HeaderCheckMixin):
|
|
656
659
|
response = requests.get("http://127.0.0.1:%i/stop" % self.web_port)
|
657
660
|
self.assertEqual(response.json()["message"], "Test stopped")
|
658
661
|
|
662
|
+
def test_swarm_shape_class_is_updated_when_userclass_picker_is_active(self):
|
663
|
+
class User1(User):
|
664
|
+
pass
|
665
|
+
|
666
|
+
class TestShape(LoadTestShape):
|
667
|
+
def tick(self):
|
668
|
+
pass
|
669
|
+
|
670
|
+
test_shape_instance = TestShape()
|
671
|
+
|
672
|
+
self.environment.web_ui.userclass_picker_is_active = True
|
673
|
+
self.environment.available_user_classes = {"User1": User1}
|
674
|
+
self.environment.available_shape_classes = {"TestShape": test_shape_instance}
|
675
|
+
self.environment.shape_class = None
|
676
|
+
|
677
|
+
response = requests.post(
|
678
|
+
"http://127.0.0.1:%i/swarm" % self.web_port,
|
679
|
+
data={
|
680
|
+
"user_count": 5,
|
681
|
+
"spawn_rate": 5,
|
682
|
+
"host": "https://localhost",
|
683
|
+
"user_classes": "User1",
|
684
|
+
"shape_class": "TestShape",
|
685
|
+
},
|
686
|
+
)
|
687
|
+
|
688
|
+
self.assertEqual(200, response.status_code)
|
689
|
+
self.assertEqual(test_shape_instance, self.environment.shape_class)
|
690
|
+
self.assertIsNotNone(test_shape_instance.runner)
|
691
|
+
|
692
|
+
# stop
|
693
|
+
gevent.sleep(1)
|
694
|
+
response = requests.get("http://127.0.0.1:%i/stop" % self.web_port)
|
695
|
+
self.assertEqual(response.json()["message"], "Test stopped")
|
696
|
+
|
659
697
|
def test_swarm_userclass_shapeclass_ignored_when_userclass_picker_is_inactive(self):
|
660
698
|
class User1(User):
|
661
699
|
wait_time = constant(1)
|
@@ -1027,17 +1065,76 @@ class TestWebUI(LocustTestCase, _HeaderCheckMixin):
|
|
1027
1065
|
|
1028
1066
|
self.assertIn(log_line, response.json().get("logs"))
|
1029
1067
|
|
1068
|
+
def test_template_args(self):
|
1069
|
+
class MyUser(User):
|
1070
|
+
@task
|
1071
|
+
def do_something(self):
|
1072
|
+
self.client.get("/")
|
1073
|
+
|
1074
|
+
host = "http://example.com"
|
1075
|
+
|
1076
|
+
class MyUser2(User):
|
1077
|
+
host = "http://example.com"
|
1078
|
+
|
1079
|
+
self.environment.user_classes = [MyUser, MyUser2]
|
1080
|
+
self.environment.available_user_classes = {"User1": MyUser, "User2": MyUser2}
|
1081
|
+
self.environment.available_user_tasks = {"User1": MyUser.tasks, "User2": MyUser2.tasks}
|
1082
|
+
|
1083
|
+
users = {"User1": MyUser.json(), "User2": MyUser2.json()}
|
1084
|
+
available_user_tasks = {"User1": ["do_something"], "User2": []}
|
1085
|
+
|
1086
|
+
self.web_ui.update_template_args()
|
1087
|
+
|
1088
|
+
self.assertEqual(self.web_ui.template_args.get("users"), users)
|
1089
|
+
self.assertEqual(
|
1090
|
+
self.web_ui.template_args.get("available_user_classes"), sorted(self.environment.available_user_classes)
|
1091
|
+
)
|
1092
|
+
self.assertEqual(self.web_ui.template_args.get("available_user_tasks"), available_user_tasks)
|
1093
|
+
|
1094
|
+
def test_update_user_endpoint(self):
|
1095
|
+
class MyUser(User):
|
1096
|
+
@task
|
1097
|
+
def my_task(self):
|
1098
|
+
pass
|
1099
|
+
|
1100
|
+
@task
|
1101
|
+
def my_task_2(self):
|
1102
|
+
pass
|
1103
|
+
|
1104
|
+
host = "http://example.com"
|
1105
|
+
|
1106
|
+
class MyUser2(User):
|
1107
|
+
host = "http://example.com"
|
1108
|
+
|
1109
|
+
self.environment.user_classes = [MyUser, MyUser2]
|
1110
|
+
self.environment.available_user_classes = {"User1": MyUser, "User2": MyUser2}
|
1111
|
+
self.environment.available_user_tasks = {"User1": MyUser.tasks, "User2": MyUser2.tasks}
|
1112
|
+
|
1113
|
+
users = {"User1": MyUser.json(), "User2": MyUser2.json()}
|
1114
|
+
available_user_tasks = {"User1": ["my_task", "my_task_2"], "User2": []}
|
1115
|
+
|
1116
|
+
# environment.update_user_class({"user_class_name": "User1", "host": "http://localhost", "tasks": ["my_task_2"]})
|
1117
|
+
response = requests.post(
|
1118
|
+
"http://127.0.0.1:%i/user" % self.web_port,
|
1119
|
+
json={"user_class_name": "User1", "host": "http://localhost", "tasks": ["my_task_2"]},
|
1120
|
+
)
|
1121
|
+
|
1122
|
+
self.assertEqual(
|
1123
|
+
self.environment.available_user_classes["User1"].json(),
|
1124
|
+
{"host": "http://localhost", "tasks": ["my_task_2"], "fixed_count": 0, "weight": 1},
|
1125
|
+
)
|
1126
|
+
|
1030
1127
|
|
1031
1128
|
class TestWebUIAuth(LocustTestCase):
|
1032
1129
|
def setUp(self):
|
1033
1130
|
super().setUp()
|
1034
1131
|
|
1035
1132
|
parser = get_parser(default_config_files=[])
|
1036
|
-
|
1037
|
-
|
1038
|
-
self.
|
1039
|
-
|
1040
|
-
self.web_ui.app.
|
1133
|
+
self.environment.parsed_options = parser.parse_args(["--modern-ui", "--web-login"])
|
1134
|
+
|
1135
|
+
self.web_ui = self.environment.create_web_ui("127.0.0.1", 0, modern_ui=True, web_login=True)
|
1136
|
+
|
1137
|
+
self.web_ui.app.secret_key = "secret!"
|
1041
1138
|
gevent.sleep(0.01)
|
1042
1139
|
self.web_port = self.web_ui.server.server_port
|
1043
1140
|
|
@@ -1046,18 +1143,36 @@ class TestWebUIAuth(LocustTestCase):
|
|
1046
1143
|
self.web_ui.stop()
|
1047
1144
|
self.runner.quit()
|
1048
1145
|
|
1049
|
-
def
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1146
|
+
def test_index_with_web_login_enabled_valid_user(self):
|
1147
|
+
class User(UserMixin):
|
1148
|
+
def __init__(self):
|
1149
|
+
self.username = "test_user"
|
1053
1150
|
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
)
|
1151
|
+
def get_id(self):
|
1152
|
+
return self.username
|
1153
|
+
|
1154
|
+
def load_user(id):
|
1155
|
+
return User()
|
1156
|
+
|
1157
|
+
self.web_ui.login_manager.request_loader(load_user)
|
1158
|
+
|
1159
|
+
response = requests.get("http://127.0.0.1:%i" % self.web_port)
|
1160
|
+
d = pq(response.content.decode("utf-8"))
|
1161
|
+
|
1162
|
+
self.assertNotIn("authArgs", str(d))
|
1163
|
+
self.assertIn("templateArgs", str(d))
|
1164
|
+
|
1165
|
+
def test_index_with_web_login_enabled_no_user(self):
|
1166
|
+
def load_user():
|
1167
|
+
return None
|
1168
|
+
|
1169
|
+
self.web_ui.login_manager.user_loader(load_user)
|
1170
|
+
|
1171
|
+
response = requests.get("http://127.0.0.1:%i" % self.web_port)
|
1172
|
+
d = pq(response.content.decode("utf-8"))
|
1058
1173
|
|
1059
|
-
|
1060
|
-
self.
|
1174
|
+
# asserts auth page is returned
|
1175
|
+
self.assertIn("authArgs", str(d))
|
1061
1176
|
|
1062
1177
|
|
1063
1178
|
class TestWebUIWithTLS(LocustTestCase):
|
locust/test/test_zmqrpc.py
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
from locust.exception import RPCError, RPCReceiveError, RPCSendError
|
2
|
+
from locust.rpc import Message, zmqrpc
|
3
|
+
from locust.test.testcases import LocustTestCase
|
4
|
+
|
1
5
|
from time import sleep
|
6
|
+
|
2
7
|
import zmq
|
3
|
-
from locust.rpc import zmqrpc, Message
|
4
|
-
from locust.test.testcases import LocustTestCase
|
5
|
-
from locust.exception import RPCError, RPCSendError, RPCReceiveError
|
6
8
|
|
7
9
|
|
8
10
|
class ZMQRPC_tests(LocustTestCase):
|
locust/test/testcases.py
CHANGED
@@ -1,3 +1,10 @@
|
|
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
|
+
|
1
8
|
import base64
|
2
9
|
import logging
|
3
10
|
import random
|
@@ -10,13 +17,6 @@ import gevent
|
|
10
17
|
import gevent.pywsgi
|
11
18
|
from flask import Flask, Response, make_response, redirect, request, send_file, stream_with_context
|
12
19
|
|
13
|
-
import locust
|
14
|
-
from locust import log
|
15
|
-
from locust.event import Events
|
16
|
-
from locust.env import Environment
|
17
|
-
from locust.test.mock_logging import MockedLoggingHandler
|
18
|
-
from locust.test.util import clear_all_functools_lru_cache
|
19
|
-
|
20
20
|
app = Flask(__name__)
|
21
21
|
app.jinja_env.add_extension("jinja2.ext.do")
|
22
22
|
|
locust/test/util.py
CHANGED
@@ -1,17 +1,16 @@
|
|
1
|
+
import datetime
|
1
2
|
import functools
|
2
3
|
import gc
|
3
4
|
import os
|
4
5
|
import socket
|
5
|
-
import
|
6
|
+
from contextlib import contextmanager
|
7
|
+
from tempfile import NamedTemporaryFile
|
8
|
+
|
6
9
|
from cryptography import x509
|
7
|
-
from cryptography.x509.oid import NameOID
|
8
|
-
from cryptography.hazmat.primitives import hashes
|
9
10
|
from cryptography.hazmat.backends import default_backend
|
10
|
-
from cryptography.hazmat.primitives import serialization
|
11
|
+
from cryptography.hazmat.primitives import hashes, serialization
|
11
12
|
from cryptography.hazmat.primitives.asymmetric import rsa
|
12
|
-
|
13
|
-
from contextlib import contextmanager
|
14
|
-
from tempfile import NamedTemporaryFile
|
13
|
+
from cryptography.x509.oid import NameOID
|
15
14
|
|
16
15
|
|
17
16
|
@contextmanager
|
locust/user/__init__.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
from .task import
|
1
|
+
from .task import TaskSet, tag, task
|
2
2
|
from .users import HttpUser, User
|