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.
Files changed (64) hide show
  1. locust/__init__.py +7 -7
  2. locust/_version.py +2 -2
  3. locust/argument_parser.py +35 -18
  4. locust/clients.py +7 -6
  5. locust/contrib/fasthttp.py +42 -37
  6. locust/debug.py +14 -8
  7. locust/dispatch.py +25 -25
  8. locust/env.py +45 -37
  9. locust/event.py +13 -10
  10. locust/exception.py +0 -9
  11. locust/html.py +9 -8
  12. locust/input_events.py +7 -5
  13. locust/main.py +95 -47
  14. locust/rpc/protocol.py +4 -2
  15. locust/rpc/zmqrpc.py +6 -4
  16. locust/runners.py +69 -76
  17. locust/shape.py +7 -4
  18. locust/stats.py +73 -71
  19. locust/templates/index.html +8 -23
  20. locust/test/mock_logging.py +7 -5
  21. locust/test/test_debugging.py +4 -4
  22. locust/test/test_dispatch.py +10 -9
  23. locust/test/test_env.py +30 -1
  24. locust/test/test_fasthttp.py +9 -8
  25. locust/test/test_http.py +4 -3
  26. locust/test/test_interruptable_task.py +4 -4
  27. locust/test/test_load_locustfile.py +6 -5
  28. locust/test/test_locust_class.py +11 -5
  29. locust/test/test_log.py +5 -4
  30. locust/test/test_main.py +37 -7
  31. locust/test/test_parser.py +11 -15
  32. locust/test/test_runners.py +22 -21
  33. locust/test/test_sequential_taskset.py +3 -2
  34. locust/test/test_stats.py +16 -18
  35. locust/test/test_tags.py +3 -2
  36. locust/test/test_taskratio.py +3 -3
  37. locust/test/test_users.py +3 -3
  38. locust/test/test_util.py +3 -2
  39. locust/test/test_wait_time.py +3 -3
  40. locust/test/test_web.py +142 -27
  41. locust/test/test_zmqrpc.py +5 -3
  42. locust/test/testcases.py +7 -7
  43. locust/test/util.py +6 -7
  44. locust/user/__init__.py +1 -1
  45. locust/user/inspectuser.py +6 -5
  46. locust/user/sequential_taskset.py +3 -1
  47. locust/user/task.py +22 -27
  48. locust/user/users.py +17 -7
  49. locust/util/deprecation.py +0 -1
  50. locust/util/exception_handler.py +1 -1
  51. locust/util/load_locustfile.py +4 -2
  52. locust/web.py +102 -53
  53. locust/webui/dist/assets/auth-5e21717c.js.map +1 -0
  54. locust/webui/dist/assets/{index-01afe4fa.js → index-a83a5dd9.js} +85 -84
  55. locust/webui/dist/assets/index-a83a5dd9.js.map +1 -0
  56. locust/webui/dist/auth.html +20 -0
  57. locust/webui/dist/index.html +1 -1
  58. {locust-2.20.1.dev28.dist-info → locust-2.20.2.dist-info}/METADATA +2 -2
  59. locust-2.20.2.dist-info/RECORD +105 -0
  60. locust-2.20.1.dev28.dist-info/RECORD +0 -102
  61. {locust-2.20.1.dev28.dist-info → locust-2.20.2.dist-info}/LICENSE +0 -0
  62. {locust-2.20.1.dev28.dist-info → locust-2.20.2.dist-info}/WHEEL +0 -0
  63. {locust-2.20.1.dev28.dist-info → locust-2.20.2.dist-info}/entry_points.txt +0 -0
  64. {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, User, TaskSet
4
+ from locust.user import HttpUser, TaskSet, User
8
5
  from locust.util.load_locustfile import is_user_class
9
- from .mock_locustfile import mock_locustfile, MOCK_LOCUSTFILE_CONTENT
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
 
@@ -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 unittest import mock
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 locust import log
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
- from subprocess import PIPE, STDOUT, DEVNULL
16
+
17
17
  import gevent
18
+ import psutil
18
19
  import requests
19
20
 
20
- from .mock_locustfile import mock_locustfile, MOCK_LOCUSTFILE_CONTENT
21
- from .util import temporary_file, get_free_tcp_port, patch_env
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(
@@ -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
- locustfile_is_directory,
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):
@@ -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, StopUser, RPCReceiveError
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
- STATE_STOPPING,
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, task, constant
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, task, User, constant, __version__
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
- PERCENTILES_TO_REPORT,
20
- STATS_NAME_WIDTH,
21
- STATS_TYPE_WIDTH,
14
+ stats_history,
22
15
  )
23
- from locust.stats import StatsCSVFileWriter
24
- from locust.stats import stats_history
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
- from locust.test.testcases import WebserverTestCase
29
- from locust.test.test_runners import mocked_rpc
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, task, tag
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
 
@@ -1,7 +1,7 @@
1
- import unittest
1
+ from locust.user import TaskSet, User, task
2
+ from locust.user.inspectuser import _get_task_ratio, get_ratio
2
3
 
3
- from locust.user import User, TaskSet, task
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
@@ -1,6 +1,7 @@
1
- import unittest
2
- from locust.util.timespan import parse_timespan
3
1
  from locust.util.rounding import proper_round
2
+ from locust.util.timespan import parse_timespan
3
+
4
+ import unittest
4
5
 
5
6
 
6
7
  class TestParseTimespan(unittest.TestCase):
@@ -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
- options = parser.parse_args(["--web-auth", "john:doe"])
1037
- self.runner = Runner(self.environment)
1038
- self.stats = self.runner.stats
1039
- self.web_ui = self.environment.create_web_ui("127.0.0.1", 0, auth_credentials=options.web_auth)
1040
- self.web_ui.app.view_functions["request_stats"].clear_cache()
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 test_index_with_basic_auth_enabled_correct_credentials(self):
1050
- self.assertEqual(
1051
- 200, requests.get("http://127.0.0.1:%i/?ele=phino" % self.web_port, auth=("john", "doe")).status_code
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
- def test_index_with_basic_auth_enabled_incorrect_credentials(self):
1055
- self.assertEqual(
1056
- 401, requests.get("http://127.0.0.1:%i/?ele=phino" % self.web_port, auth=("john", "invalid")).status_code
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
- def test_index_with_basic_auth_enabled_blank_credentials(self):
1060
- self.assertEqual(401, requests.get("http://127.0.0.1:%i/?ele=phino" % self.web_port).status_code)
1174
+ # asserts auth page is returned
1175
+ self.assertIn("authArgs", str(d))
1061
1176
 
1062
1177
 
1063
1178
  class TestWebUIWithTLS(LocustTestCase):
@@ -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 datetime
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 task, tag, TaskSet
1
+ from .task import TaskSet, tag, task
2
2
  from .users import HttpUser, User