locust 2.29.2.dev10__tar.gz → 2.29.2.dev26__tar.gz
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-2.29.2.dev10 → locust-2.29.2.dev26}/PKG-INFO +1 -1
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/benchmarks/dispatch.py +98 -49
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/test_data_management.py +36 -11
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/_version.py +2 -2
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/event.py +32 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/runners.py +13 -22
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/test_runners.py +145 -11
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust.egg-info/PKG-INFO +1 -1
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/.coveragerc +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/.dockerignore +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/.git-blame-ignore-revs +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/.gitattributes +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/.github/CONTRIBUTING.md +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/.github/ISSUE_TEMPLATE/bug.yml +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/.github/workflows/stale.yml +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/.github/workflows/tests.yml +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/.gitignore +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/.pre-commit-config.yaml +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/.readthedocs.yaml +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/.vscode/extensions.json +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/.vscode/launch.json +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/.vscode/launch_locust.json +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/.vscode/settings.json +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/CHANGELOG.md +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/Dockerfile +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/LICENSE +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/MANIFEST.in +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/Makefile +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/README.md +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/SECURITY.md +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/Vagrantfile +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/_static/theme-overrides.css +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/api.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/changelog.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/conf.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/configuration.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/custom-load-shape.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/developing-locust.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/extending-locust.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/extensions.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/faq.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/further-reading.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/history.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/images/extend_modern_web_ui_cache_stats.png +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/images/locust_workers.png +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/images/number_of_users.png +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/images/response_times.png +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/images/total_requests_per_second.png +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/images/userclass_picker_example.png +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/images/webui-running-statistics.png +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/images/webui-splash-screenshot.png +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/increase-performance.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/increasing-request-rate.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/index.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/installation.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/logging.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/quickstart.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/requirements.txt +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/retrieving-stats.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/running-distributed.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/running-in-debugger.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/running-in-docker.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/running-without-web-ui.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/tasksets.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/testing-other-systems.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/use-as-lib.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/what-is-locust.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/docs/writing-a-locustfile.rst +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/add_command_line_argument.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/basic.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/browse_docs_sequence_test.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/browse_docs_test.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/custom_messages.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/custom_shape/double_wave.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/custom_shape/stages.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/custom_shape/staging_user_classes.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/custom_shape/step_load.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/custom_shape/wait_user_count.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/custom_wait_function.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/custom_xmlrpc_client/server.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/custom_xmlrpc_client/xmlrpc_locustfile.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/debugging.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/debugging_advanced.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/dispatch_test_scripts/locustfile.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/dispatch_test_scripts/run-disributed-headless.sh +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/dispatch_test_scripts/run-disributed-web.sh +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/dispatch_test_scripts/run-local-headless.sh +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/dispatch_test_scripts/run-local-web.sh +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/docker-compose/docker-compose.yml +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/dynamic_user_credentials.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/events.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/extend_web_ui.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/fast_http_locust.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/grpc/grpc_user.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/grpc/hello.proto +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/grpc/hello_pb2.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/grpc/hello_pb2_grpc.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/grpc/hello_server.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/grpc/locustfile.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/locustfile.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/manual_stats_reporting.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/multiple_hosts.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/nested_inline_tasksets.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/rest.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/sdk_session_patching/session_patch_locustfile.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/semaphore_wait.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/stop_on_threshold.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/terraform/aws/README.md +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/terraform/aws/data_subnet.tf +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/terraform/aws/main.tf +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/terraform/aws/output.tf +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/terraform/aws/plan/basic.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/terraform/aws/provisioner.tf +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/terraform/aws/variables.tf +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/use_as_lib.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/vagrant/README.md +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/vagrant/supervisord.conf +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/web_ui_auth.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/web_ui_cache_stats.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/examples/worker_index.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/generate_changelog.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/__init__.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/__main__.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/argument_parser.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/clients.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/contrib/__init__.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/contrib/fasthttp.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/debug.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/dispatch.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/env.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/exception.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/html.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/input_events.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/log.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/main.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/py.typed +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/rpc/__init__.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/rpc/protocol.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/rpc/zmqrpc.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/shape.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/stats.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/__init__.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/fake_module1_for_env_test.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/fake_module2_for_env_test.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/mock_locustfile.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/mock_logging.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/test_debugging.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/test_dispatch.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/test_env.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/test_fasthttp.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/test_http.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/test_interruptable_task.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/test_load_locustfile.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/test_locust_class.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/test_log.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/test_main.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/test_old_wait_api.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/test_parser.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/test_sequential_taskset.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/test_stats.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/test_tags.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/test_taskratio.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/test_users.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/test_util.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/test_wait_time.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/test_web.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/test_zmqrpc.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/testcases.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/test/util.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/user/__init__.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/user/inspectuser.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/user/sequential_taskset.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/user/task.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/user/users.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/user/wait_time.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/util/__init__.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/util/cache.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/util/date.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/util/deprecation.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/util/exception_handler.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/util/load_locustfile.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/util/rounding.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/util/timespan.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/web.py +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/.eslintrc +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/.gitignore +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/.prettierrc +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/auth.html +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/dev.html +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/dist/assets/favicon.ico +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/dist/assets/logo.png +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/dist/auth.html +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/dist/index.html +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/dist/report.html +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/index.html +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/package.json +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/public/assets/favicon.ico +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/public/assets/logo.png +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/public/report.html +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/App.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/App.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/DataTable/DataTable.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/DataTable/DataTable.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/ExceptionsTable/ExceptionsTable.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/FailuresTable/FailuresTable.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/FallbackRender/FallbackRender.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/FallbackRender/FallbackRender.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/Form/Form.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/Form/Select.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/Form/tests/Form.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/Form/tests/Select.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/Layout/Footer/About.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/Layout/Footer/Footer.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/Layout/Layout.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/Layout/Navbar/DarkLightToggle.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/Layout/Navbar/Navbar.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/Layout/Navbar/SwarmMonitor.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/Layout/Navbar/SwarmMonitor.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/LineChart/LineChart.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/LineChart/LineChart.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/LogViewer/LogViewer.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/LogViewer/logUtils.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/LogViewer/tests/LogViewer.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/LogViewer/tests/useLogViewer.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/LogViewer/useLogViewer.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/Modal/Modal.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/Reports/Reports.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/Reports/Reports.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/ResponseTimeTable/ResponseTimeTable.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/ResponseTimeTable/ResponseTimeTable.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/StateButtons/EditButton.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/StateButtons/NewTestButton.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/StateButtons/ResetButton.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/StateButtons/StateButtons.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/StateButtons/StopButton.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/StateButtons/tests/ResetButton.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/StateButtons/tests/StateButtons.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/StateButtons/tests/StopButton.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/StatsTable/StatsTable.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/SwarmCharts/SwarmCharts.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/SwarmForm/SwarmCustomParameters.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/SwarmForm/SwarmEditForm.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/SwarmForm/SwarmForm.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/SwarmForm/SwarmUserClassPicker.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/SwarmForm/tests/SwarmCustomParameters.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/SwarmForm/tests/SwarmEditForm.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/SwarmForm/tests/SwarmForm.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/SwarmForm/tests/SwarmUserClassPicker.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/SwarmRatios/SwarmRatios.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/SwarmRatios/SwarmRatios.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/Table/Table.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/Table/Table.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/Tabs/Tabs.constants.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/Tabs/Tabs.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/Tabs/Tabs.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/ViewColumnSelector/ViewColumnSelector.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/ViewColumnSelector/ViewColumnSelector.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/components/WorkersTable/WorkersTable.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/constants/auth.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/constants/logs.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/constants/swarm.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/constants/theme.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/global.d.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/hooks/tests/useNotifications.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/hooks/tests/useSelecteViewColumns.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/hooks/tests/useSortByField.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/hooks/tests/useSwarmUi.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/hooks/useInterval.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/hooks/useNotifications.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/hooks/useSelectViewColumns.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/hooks/useSortByField.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/hooks/useSwarmUi.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/index.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/pages/Auth.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/pages/Dashboard.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/pages/HtmlReport.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/pages/tests/Auth.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/pages/tests/Dashboard.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/pages/tests/HtmlReport.test.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/redux/api/swarm.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/redux/hooks.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/redux/slice/logViewer.slice.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/redux/slice/notification.slice.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/redux/slice/root.slice.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/redux/slice/swarm.slice.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/redux/slice/tests/ui.slice.test.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/redux/slice/theme.slice.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/redux/slice/ui.slice.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/redux/slice/url.slice.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/redux/store.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/redux/utils.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/styles/theme.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/test/constants.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/test/mocks/statsRequest.mock.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/test/mocks/swarmState.mock.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/test/setup.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/test/testUtils.tsx +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/types/auth.types.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/types/swarm.types.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/types/tab.types.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/types/table.types.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/types/ui.types.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/utils/array.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/utils/date.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/utils/number.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/utils/object.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/utils/string.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/utils/tests/number.test.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/utils/tests/object.test.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/utils/tests/string.test.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/utils/tests/url.test.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/src/utils/url.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/tsconfig.json +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/vite.config.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/vitest.config.ts +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust/webui/yarn.lock +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust.egg-info/SOURCES.txt +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust.egg-info/dependency_links.txt +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust.egg-info/entry_points.txt +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust.egg-info/not-zip-safe +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust.egg-info/requires.txt +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/locust.egg-info/top_level.txt +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/package.json +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/pyproject.toml +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/setup.cfg +0 -0
- {locust-2.29.2.dev10 → locust-2.29.2.dev26}/tox.ini +0 -0
@@ -1,7 +1,7 @@
|
|
1
1
|
"""
|
2
2
|
This file contains a benchmark to validate the performance of Locust itself.
|
3
3
|
More precisely, the performance of the `UsersDispatcher` class which is responsible
|
4
|
-
for calculating the distribution of users on each
|
4
|
+
for calculating the distribution of users on each worker. This benchmark is to be used
|
5
5
|
by people working on Locust's development.
|
6
6
|
"""
|
7
7
|
|
@@ -9,105 +9,146 @@ from locust import User
|
|
9
9
|
from locust.dispatch import UsersDispatcher
|
10
10
|
from locust.runners import WorkerNode
|
11
11
|
|
12
|
+
import argparse
|
13
|
+
import gc
|
12
14
|
import itertools
|
13
15
|
import statistics
|
14
16
|
import time
|
15
17
|
|
16
18
|
from prettytable import PrettyTable
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
78, 76, 28, 62, 69, 5, 55, 37, 2, 97,
|
22
|
-
41, 33, 19, 19, 34, 78, 76, 28, 62, 69,
|
23
|
-
41, 33, 19, 19, 34, 78, 76, 28, 62, 69,
|
24
|
-
41, 33, 19, 19, 34, 78, 76, 28, 62, 69,
|
25
|
-
5, 55, 37, 2, 97, 41, 33, 19, 19, 34,
|
26
|
-
78, 76, 28, 62, 69, 5, 55, 37, 2, 97,
|
27
|
-
41, 33, 19, 19, 34, 78, 76, 28, 62, 69,
|
28
|
-
41, 33, 19, 19, 34, 78, 76, 28, 62, 69,
|
29
|
-
41, 33, 19, 19, 34, 78, 76, 28, 62, 69,
|
30
|
-
]
|
31
|
-
# fmt: on
|
20
|
+
NUMBER_OF_USER_CLASSES: int = 1000
|
21
|
+
USER_CLASSES: list[type[User]] = []
|
22
|
+
WEIGHTS = list(range(1, NUMBER_OF_USER_CLASSES + 1))
|
32
23
|
|
33
24
|
for i, x in enumerate(WEIGHTS):
|
34
|
-
exec(f"class User{i
|
25
|
+
exec(f"class User{i}(User): weight = {x}")
|
35
26
|
|
36
27
|
# Equivalent to:
|
37
28
|
#
|
38
|
-
# class
|
29
|
+
# class User0(User):
|
39
30
|
# weight = 5
|
40
31
|
#
|
41
|
-
# class
|
32
|
+
# class User1(User):
|
42
33
|
# weight = 55
|
43
34
|
# .
|
44
35
|
# .
|
45
36
|
# .
|
46
|
-
# class User100(User):
|
47
|
-
# weight = 69
|
48
37
|
|
49
|
-
exec("USER_CLASSES = [" + ",".join(f"User{i
|
38
|
+
exec("USER_CLASSES = [" + ",".join(f"User{i}" for i in range(len(WEIGHTS))) + "]")
|
50
39
|
# Equivalent to:
|
51
40
|
#
|
52
41
|
# USER_CLASSES = [
|
42
|
+
# User0,
|
53
43
|
# User1,
|
54
|
-
# User2,
|
55
44
|
# .
|
56
45
|
# .
|
57
46
|
# .
|
58
|
-
# User100,
|
59
47
|
# ]
|
60
48
|
|
61
49
|
|
62
50
|
if __name__ == "__main__":
|
51
|
+
parser = argparse.ArgumentParser()
|
52
|
+
parser.add_argument("-f", "--full-benchmark", action="store_true", help="run benchmark on full test matrix")
|
53
|
+
parser.add_argument(
|
54
|
+
"-i",
|
55
|
+
"--include-fixed-users",
|
56
|
+
action="store_true",
|
57
|
+
help="add test cases when 50 percent of users use User.fixed_count instead of User.weight",
|
58
|
+
)
|
59
|
+
parser.add_argument("-r", "--repeat", default=1, type=int, help="number of test cases with the same parameters")
|
60
|
+
parser.add_argument("-s", "--save-output", action="store_true", help="save test results to files")
|
61
|
+
args = parser.parse_args()
|
62
|
+
|
63
63
|
now = time.time()
|
64
64
|
|
65
|
-
worker_count_cases = [10, 100,
|
66
|
-
user_count_cases = [
|
67
|
-
number_of_user_classes_cases = [1,
|
68
|
-
spawn_rate_cases = [
|
65
|
+
worker_count_cases = [10, 100, 1000]
|
66
|
+
user_count_cases = [10_000, 100_000, 1_000_000]
|
67
|
+
number_of_user_classes_cases = [1, 30, 1000]
|
68
|
+
spawn_rate_cases = [100, 10_000]
|
69
|
+
fixed_count_cases = [False, True] if args.include_fixed_users else [False]
|
70
|
+
# [0% fixed_count users, 50% fixed_count users] if args.mixed_user_types else [0% fixed_count users]
|
71
|
+
repeat_cases = list(range(1, args.repeat + 1))
|
72
|
+
|
73
|
+
if not args.full_benchmark:
|
74
|
+
worker_count_cases = [max(worker_count_cases)]
|
75
|
+
user_count_cases = [max(user_count_cases)]
|
76
|
+
number_of_user_classes_cases = [max(number_of_user_classes_cases)]
|
77
|
+
spawn_rate_cases = [max(spawn_rate_cases)]
|
69
78
|
|
70
79
|
case_count = (
|
71
|
-
len(worker_count_cases)
|
80
|
+
len(worker_count_cases)
|
81
|
+
* len(user_count_cases)
|
82
|
+
* len(number_of_user_classes_cases)
|
83
|
+
* len(spawn_rate_cases)
|
84
|
+
* len(fixed_count_cases)
|
85
|
+
* len(repeat_cases)
|
72
86
|
)
|
73
87
|
|
74
88
|
results = {}
|
75
89
|
|
76
90
|
try:
|
77
|
-
for case_index, (
|
78
|
-
|
91
|
+
for case_index, (
|
92
|
+
worker_count,
|
93
|
+
user_count,
|
94
|
+
number_of_user_classes,
|
95
|
+
spawn_rate,
|
96
|
+
fixed_users,
|
97
|
+
iteration,
|
98
|
+
) in enumerate(
|
99
|
+
itertools.product(
|
100
|
+
worker_count_cases,
|
101
|
+
user_count_cases,
|
102
|
+
number_of_user_classes_cases,
|
103
|
+
spawn_rate_cases,
|
104
|
+
fixed_count_cases,
|
105
|
+
repeat_cases,
|
106
|
+
)
|
79
107
|
):
|
80
|
-
|
81
|
-
|
82
|
-
|
108
|
+
workers = [WorkerNode(str(i)) for i in range(worker_count)]
|
109
|
+
if fixed_users:
|
110
|
+
sum_fixed_weight = 0
|
111
|
+
for j in range(0, number_of_user_classes, 2):
|
112
|
+
sum_fixed_weight += USER_CLASSES[j].weight
|
83
113
|
|
84
|
-
|
114
|
+
for j in range(0, number_of_user_classes, 2): # set fixed_weights for 50% of users
|
115
|
+
USER_CLASSES[j].fixed_count = max(1, USER_CLASSES[j].weight // sum_fixed_weight) # type: ignore # assigned .weight is int
|
85
116
|
|
86
|
-
ts = time.
|
117
|
+
ts = time.process_time()
|
87
118
|
users_dispatcher = UsersDispatcher(
|
88
119
|
worker_nodes=workers,
|
89
|
-
user_classes=USER_CLASSES[:number_of_user_classes],
|
120
|
+
user_classes=USER_CLASSES[:number_of_user_classes],
|
90
121
|
)
|
91
|
-
instantiate_duration = time.
|
122
|
+
instantiate_duration = time.process_time() - ts
|
92
123
|
|
93
124
|
# Ramp-up
|
94
|
-
|
125
|
+
gc.disable()
|
126
|
+
ts = time.process_time()
|
95
127
|
users_dispatcher.new_dispatch(target_user_count=user_count, spawn_rate=spawn_rate)
|
96
|
-
new_dispatch_ramp_up_duration = time.
|
128
|
+
new_dispatch_ramp_up_duration = time.process_time() - ts
|
129
|
+
gc.enable()
|
130
|
+
|
97
131
|
assert len(users_dispatcher.dispatch_iteration_durations) == 0
|
98
132
|
users_dispatcher._wait_between_dispatch = 0
|
99
133
|
all_dispatched_users_ramp_up = list(users_dispatcher)
|
100
134
|
dispatch_iteration_durations_ramp_up = users_dispatcher.dispatch_iteration_durations[:]
|
101
135
|
|
102
136
|
# Ramp-down
|
103
|
-
|
137
|
+
gc.disable()
|
138
|
+
ts = time.process_time()
|
104
139
|
users_dispatcher.new_dispatch(target_user_count=0, spawn_rate=spawn_rate)
|
105
|
-
new_dispatch_ramp_down_duration = time.
|
140
|
+
new_dispatch_ramp_down_duration = time.process_time() - ts
|
141
|
+
gc.enable()
|
142
|
+
|
106
143
|
assert len(users_dispatcher.dispatch_iteration_durations) == 0
|
107
144
|
users_dispatcher._wait_between_dispatch = 0
|
108
145
|
all_dispatched_users_ramp_down = list(users_dispatcher)
|
109
146
|
dispatch_iteration_durations_ramp_down = users_dispatcher.dispatch_iteration_durations[:]
|
110
147
|
|
148
|
+
if fixed_users:
|
149
|
+
for j in range(0, number_of_user_classes, 2):
|
150
|
+
USER_CLASSES[j].fixed_count = None
|
151
|
+
|
111
152
|
cpu_ramp_up = "{:3.3f}/{:3.3f}/{:3.3f}".format( # noqa: UP032
|
112
153
|
1000 * statistics.mean(dispatch_iteration_durations_ramp_up),
|
113
154
|
1000 * min(dispatch_iteration_durations_ramp_up),
|
@@ -135,7 +176,10 @@ if __name__ == "__main__":
|
|
135
176
|
)
|
136
177
|
)
|
137
178
|
|
138
|
-
results[(worker_count, user_count, number_of_user_classes, spawn_rate)] = (
|
179
|
+
results[(worker_count, user_count, number_of_user_classes, spawn_rate, fixed_users, iteration)] = (
|
180
|
+
cpu_ramp_up,
|
181
|
+
cpu_ramp_down,
|
182
|
+
)
|
139
183
|
|
140
184
|
finally:
|
141
185
|
table = PrettyTable()
|
@@ -144,6 +188,8 @@ if __name__ == "__main__":
|
|
144
188
|
"Users",
|
145
189
|
"User Classes",
|
146
190
|
"Spawn Rate",
|
191
|
+
"Fixed Users",
|
192
|
+
"Iteration",
|
147
193
|
"Ramp-Up (avg/min/max) (ms)",
|
148
194
|
"Ramp-Down (avg/min/max) (ms)",
|
149
195
|
]
|
@@ -151,6 +197,8 @@ if __name__ == "__main__":
|
|
151
197
|
table.align["Users"] = "l"
|
152
198
|
table.align["User Classes"] = "l"
|
153
199
|
table.align["Spawn Rate"] = "l"
|
200
|
+
table.align["Fixed Users"] = "l"
|
201
|
+
table.align["Iteration"] = "c"
|
154
202
|
table.align["Ramp-Up (avg/min/max) (ms)"] = "c"
|
155
203
|
table.align["Ramp-Down (avg/min/max) (ms)"] = "c"
|
156
204
|
table.add_rows(
|
@@ -160,22 +208,23 @@ if __name__ == "__main__":
|
|
160
208
|
f"{user_count:,}",
|
161
209
|
number_of_user_classes,
|
162
210
|
f"{spawn_rate:,}",
|
211
|
+
"50%" if fixed_users else "0%",
|
212
|
+
iteration,
|
163
213
|
cpu_ramp_up,
|
164
214
|
cpu_ramp_down,
|
165
215
|
]
|
166
|
-
for (worker_count, user_count, number_of_user_classes, spawn_rate), (
|
216
|
+
for (worker_count, user_count, number_of_user_classes, spawn_rate, fixed_users, iteration), (
|
167
217
|
cpu_ramp_up,
|
168
218
|
cpu_ramp_down,
|
169
219
|
) in results.items()
|
170
220
|
]
|
171
221
|
)
|
172
222
|
print()
|
173
|
-
print()
|
174
|
-
print()
|
175
223
|
print(table)
|
176
224
|
|
177
|
-
|
178
|
-
|
225
|
+
if args.save_output:
|
226
|
+
with open(f"results-dispatch-benchmarks-{int(now)}.txt", "w") as file:
|
227
|
+
file.write(table.get_string())
|
179
228
|
|
180
|
-
|
181
|
-
|
229
|
+
with open(f"results-dispatch-benchmarks-{int(now)}.json", "w") as file:
|
230
|
+
file.write(table.get_json_string())
|
@@ -6,6 +6,10 @@
|
|
6
6
|
# 3. Test start
|
7
7
|
# 4. User start
|
8
8
|
# 5. Inside a task
|
9
|
+
# M1. CPU & memory usage
|
10
|
+
# M2. master sent heartbeat to worker 1-N
|
11
|
+
# M3. worker 1-N received heartbeat from master
|
12
|
+
# (M* are repeated as long as locust is running)
|
9
13
|
# ...
|
10
14
|
# 6. Test run stopping
|
11
15
|
# 7. User stop
|
@@ -15,17 +19,21 @@
|
|
15
19
|
# 10. Locust quit
|
16
20
|
#
|
17
21
|
# try it out by running:
|
18
|
-
# locust -f test_data_management.py --headless -u 2 -t 5
|
22
|
+
# locust -f test_data_management.py --headless -u 2 -t 5 --processes 2
|
23
|
+
from __future__ import annotations
|
24
|
+
|
19
25
|
from locust import HttpUser, events, task
|
26
|
+
from locust.env import Environment
|
20
27
|
from locust.runners import MasterRunner
|
21
28
|
from locust.user.wait_time import constant
|
22
29
|
|
23
30
|
import datetime
|
31
|
+
from typing import Any
|
24
32
|
|
25
33
|
import requests
|
26
34
|
|
27
35
|
|
28
|
-
def timestring():
|
36
|
+
def timestring() -> str:
|
29
37
|
now = datetime.datetime.now()
|
30
38
|
return datetime.datetime.strftime(now, "%m:%S.%f")[:-5]
|
31
39
|
|
@@ -42,17 +50,17 @@ test_run_specific_data = None
|
|
42
50
|
|
43
51
|
|
44
52
|
@events.init.add_listener
|
45
|
-
def init(environment, **_kwargs):
|
53
|
+
def init(environment: Environment, **_kwargs: Any) -> None:
|
46
54
|
print("2. Initializing locust, happens after parsing the locustfile but before test start")
|
47
55
|
|
48
56
|
|
49
57
|
@events.quitting.add_listener
|
50
|
-
def quitting(environment, **_kwargs):
|
58
|
+
def quitting(environment: Environment, **_kwargs: Any) -> None:
|
51
59
|
print("9. locust is about to shut down")
|
52
60
|
|
53
61
|
|
54
62
|
@events.test_start.add_listener
|
55
|
-
def test_start(environment, **_kwargs):
|
63
|
+
def test_start(environment: Environment, **_kwargs) -> None:
|
56
64
|
# happens only once in headless runs, but can happen multiple times in web ui-runs
|
57
65
|
global test_run_specific_data
|
58
66
|
print("3. Starting test run")
|
@@ -64,18 +72,35 @@ def test_start(environment, **_kwargs):
|
|
64
72
|
).json()["data"]
|
65
73
|
|
66
74
|
|
75
|
+
@events.heartbeat_sent.add_listener
|
76
|
+
def heartbeat_sent(client_id: str, timestamp: float) -> None:
|
77
|
+
print(f"M2. master sent heartbeat to worker {client_id} at {datetime.datetime.fromtimestamp(timestamp)}")
|
78
|
+
|
79
|
+
|
80
|
+
@events.heartbeat_received.add_listener
|
81
|
+
def heartbeat_received(client_id: str, timestamp: float) -> None:
|
82
|
+
print(f"M3. worker {client_id} received heartbeat from master at {datetime.datetime.fromtimestamp(timestamp)}")
|
83
|
+
|
84
|
+
|
85
|
+
@events.usage_monitor.add_listener
|
86
|
+
def usage_monitor(environment: Environment, cpu_usage: float, memory_usage: int) -> None:
|
87
|
+
# convert from bytes to Mebibytes
|
88
|
+
memory_usage = memory_usage / 1024 / 1024
|
89
|
+
print(f"M1. {environment.runner.__class__.__name__}: cpu={cpu_usage}%, memory={memory_usage}M")
|
90
|
+
|
91
|
+
|
67
92
|
@events.quit.add_listener
|
68
|
-
def quit(exit_code, **kwargs):
|
93
|
+
def quit(exit_code: int, **kwargs: Any) -> None:
|
69
94
|
print(f"10. Locust has shut down with code {exit_code}")
|
70
95
|
|
71
96
|
|
72
97
|
@events.test_stopping.add_listener
|
73
|
-
def test_stopping(environment, **_kwargs):
|
98
|
+
def test_stopping(environment: Environment, **_kwargs: Any) -> None:
|
74
99
|
print("6. stopping test run")
|
75
100
|
|
76
101
|
|
77
102
|
@events.test_stop.add_listener
|
78
|
-
def test_stop(environment, **_kwargs):
|
103
|
+
def test_stop(environment: Environment, **_kwargs: Any) -> None:
|
79
104
|
print("8. test run stopped")
|
80
105
|
|
81
106
|
|
@@ -84,7 +109,7 @@ class MyUser(HttpUser):
|
|
84
109
|
wait_time = constant(180) # be nice to postman-echo
|
85
110
|
first_start = True
|
86
111
|
|
87
|
-
def on_start(self):
|
112
|
+
def on_start(self) -> None:
|
88
113
|
if MyUser.first_start:
|
89
114
|
MyUser.first_start = False
|
90
115
|
# This is useful for similar things as to test_start, but happens in the context of a User
|
@@ -101,7 +126,7 @@ class MyUser(HttpUser):
|
|
101
126
|
).json()["data"]
|
102
127
|
|
103
128
|
@task
|
104
|
-
def t(self):
|
129
|
+
def t(self) -> None:
|
105
130
|
self.client.get(f"/get?{global_test_data}")
|
106
131
|
self.client.get(f"/get?{test_run_specific_data}")
|
107
132
|
self.client.get(f"/get?{self.user_specific_testdata}")
|
@@ -114,6 +139,6 @@ class MyUser(HttpUser):
|
|
114
139
|
).json()["data"]
|
115
140
|
self.client.get(f"/get?{task_run_specific_testdata}")
|
116
141
|
|
117
|
-
def on_stop(self):
|
142
|
+
def on_stop(self) -> None:
|
118
143
|
# this is a good place to clean up/release any user-specific test data
|
119
144
|
print("7. a user was stopped")
|
@@ -12,5 +12,5 @@ __version__: str
|
|
12
12
|
__version_tuple__: VERSION_TUPLE
|
13
13
|
version_tuple: VERSION_TUPLE
|
14
14
|
|
15
|
-
__version__ = version = '2.29.2.
|
16
|
-
__version_tuple__ = version_tuple = (2, 29, 2, '
|
15
|
+
__version__ = version = '2.29.2.dev26'
|
16
|
+
__version_tuple__ = version_tuple = (2, 29, 2, 'dev26')
|
@@ -235,6 +235,38 @@ class Events:
|
|
235
235
|
Fired when the CPU usage exceeds runners.CPU_WARNING_THRESHOLD (90% by default)
|
236
236
|
"""
|
237
237
|
|
238
|
+
heartbeat_sent: EventHook
|
239
|
+
"""
|
240
|
+
Fired when a heartbeat is sent by master to a worker.
|
241
|
+
|
242
|
+
Event arguments:
|
243
|
+
|
244
|
+
:param client_id: worker client id
|
245
|
+
:param timestamp: time in seconds since the epoch (float) when the event occured
|
246
|
+
"""
|
247
|
+
|
248
|
+
heartbeat_received: EventHook
|
249
|
+
"""
|
250
|
+
Fired when a heartbeat is received by a worker from master.
|
251
|
+
|
252
|
+
Event arguments:
|
253
|
+
|
254
|
+
:param client_id: worker client id
|
255
|
+
:param timestamp: time in seconds since the epoch (float) when the event occured
|
256
|
+
"""
|
257
|
+
|
258
|
+
usage_monitor: EventHook
|
259
|
+
"""
|
260
|
+
Fired every runners.CPU_MONITOR_INTERVAL (5.0 seconds by default) with information about
|
261
|
+
current CPU and memory usage.
|
262
|
+
|
263
|
+
Event arguments:
|
264
|
+
|
265
|
+
:param environment: locust environment
|
266
|
+
:param cpu_usage: current CPU usage in percent
|
267
|
+
:param memory_usage: current memory usage (RSS) in bytes
|
268
|
+
"""
|
269
|
+
|
238
270
|
def __init__(self):
|
239
271
|
# For backward compatibility use also values of class attributes
|
240
272
|
for name, value in vars(type(self)).items():
|
@@ -15,19 +15,9 @@ import traceback
|
|
15
15
|
from abc import abstractmethod
|
16
16
|
from collections import defaultdict
|
17
17
|
from collections.abc import Iterator, MutableMapping, ValuesView
|
18
|
-
from operator import
|
19
|
-
itemgetter,
|
20
|
-
methodcaller,
|
21
|
-
)
|
18
|
+
from operator import itemgetter, methodcaller
|
22
19
|
from types import TracebackType
|
23
|
-
from typing import
|
24
|
-
TYPE_CHECKING,
|
25
|
-
Any,
|
26
|
-
Callable,
|
27
|
-
NoReturn,
|
28
|
-
TypedDict,
|
29
|
-
cast,
|
30
|
-
)
|
20
|
+
from typing import TYPE_CHECKING, Any, Callable, NoReturn, TypedDict, cast
|
31
21
|
from uuid import uuid4
|
32
22
|
|
33
23
|
import gevent
|
@@ -40,15 +30,8 @@ from . import argument_parser
|
|
40
30
|
from .dispatch import UsersDispatcher
|
41
31
|
from .exception import RPCError, RPCReceiveError, RPCSendError
|
42
32
|
from .log import get_logs, greenlet_exception_logger
|
43
|
-
from .rpc import
|
44
|
-
|
45
|
-
rpc,
|
46
|
-
)
|
47
|
-
from .stats import (
|
48
|
-
RequestStats,
|
49
|
-
StatsError,
|
50
|
-
setup_distributed_stats_event_listeners,
|
51
|
-
)
|
33
|
+
from .rpc import Message, rpc
|
34
|
+
from .stats import RequestStats, StatsError, setup_distributed_stats_event_listeners
|
52
35
|
|
53
36
|
if TYPE_CHECKING:
|
54
37
|
from . import User
|
@@ -106,7 +89,7 @@ class Runner:
|
|
106
89
|
self.spawning_greenlet: gevent.Greenlet | None = None
|
107
90
|
self.shape_greenlet: gevent.Greenlet | None = None
|
108
91
|
self.shape_last_tick: tuple[int, float] | tuple[int, float, list[type[User]] | None] | None = None
|
109
|
-
self.current_cpu_usage:
|
92
|
+
self.current_cpu_usage: float = 0.0
|
110
93
|
self.cpu_warning_emitted: bool = False
|
111
94
|
self.worker_cpu_warning_emitted: bool = False
|
112
95
|
self.current_memory_usage: int = 0
|
@@ -308,6 +291,10 @@ class Runner:
|
|
308
291
|
f"CPU usage above {CPU_WARNING_THRESHOLD}%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines"
|
309
292
|
)
|
310
293
|
self.cpu_warning_emitted = True
|
294
|
+
|
295
|
+
self.environment.events.usage_monitor.fire(
|
296
|
+
environment=self.environment, cpu_usage=self.current_cpu_usage, memory_usage=self.current_memory_usage
|
297
|
+
)
|
311
298
|
gevent.sleep(CPU_MONITOR_INTERVAL)
|
312
299
|
|
313
300
|
@abstractmethod
|
@@ -1102,6 +1089,7 @@ class MasterRunner(DistributedRunner):
|
|
1102
1089
|
)
|
1103
1090
|
if "current_memory_usage" in msg.data:
|
1104
1091
|
c.memory_usage = msg.data["current_memory_usage"]
|
1092
|
+
self.environment.events.heartbeat_sent.fire(client_id=msg.node_id, timestamp=time.time())
|
1105
1093
|
self.server.send_to_client(Message("heartbeat", None, msg.node_id))
|
1106
1094
|
else:
|
1107
1095
|
logging.debug(f"Got heartbeat message from unknown worker {msg.node_id}")
|
@@ -1399,6 +1387,9 @@ class WorkerRunner(DistributedRunner):
|
|
1399
1387
|
self.reset_connection()
|
1400
1388
|
elif msg.type == "heartbeat":
|
1401
1389
|
self.last_heartbeat_timestamp = time.time()
|
1390
|
+
self.environment.events.heartbeat_received.fire(
|
1391
|
+
client_id=msg.node_id, timestamp=self.last_heartbeat_timestamp
|
1392
|
+
)
|
1402
1393
|
elif msg.type == "update_user_class":
|
1403
1394
|
self.environment.update_user_class(msg.data)
|
1404
1395
|
elif msg.type == "spawning_complete":
|
@@ -1,12 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import locust
|
4
|
-
from locust import
|
5
|
-
LoadTestShape,
|
6
|
-
__version__,
|
7
|
-
constant,
|
8
|
-
runners,
|
9
|
-
)
|
4
|
+
from locust import LoadTestShape, __version__, constant, runners
|
10
5
|
from locust.argument_parser import parse_options
|
11
6
|
from locust.dispatch import UsersDispatcher
|
12
7
|
from locust.env import Environment
|
@@ -26,11 +21,7 @@ from locust.runners import (
|
|
26
21
|
WorkerRunner,
|
27
22
|
)
|
28
23
|
from locust.stats import RequestStats
|
29
|
-
from locust.user import
|
30
|
-
TaskSet,
|
31
|
-
User,
|
32
|
-
task,
|
33
|
-
)
|
24
|
+
from locust.user import TaskSet, User, task
|
34
25
|
|
35
26
|
import json
|
36
27
|
import logging
|
@@ -2136,6 +2127,149 @@ class TestMasterWorkerRunners(LocustTestCase):
|
|
2136
2127
|
|
2137
2128
|
self.assertEqual(test_start_exec_count, 1)
|
2138
2129
|
|
2130
|
+
def test_heartbeat_event(self) -> None:
|
2131
|
+
"""
|
2132
|
+
Tests that heartbeat event is fired during a test
|
2133
|
+
"""
|
2134
|
+
|
2135
|
+
class TestUser(User):
|
2136
|
+
wait_time = constant(0.1)
|
2137
|
+
|
2138
|
+
@task
|
2139
|
+
def noop(self) -> None:
|
2140
|
+
pass
|
2141
|
+
|
2142
|
+
with mock.patch("locust.runners.HEARTBEAT_INTERVAL", new=1):
|
2143
|
+
# start a Master runner
|
2144
|
+
master_env = Environment(user_classes=[TestUser])
|
2145
|
+
worker_connect_events = []
|
2146
|
+
timestamp_start: list[float] = [time.time() + 3600.0]
|
2147
|
+
|
2148
|
+
def on_connect(client_id: str) -> None:
|
2149
|
+
worker_connect_events.append(client_id)
|
2150
|
+
timestamp_start[0] = time.time()
|
2151
|
+
|
2152
|
+
master_env.events.worker_connect.add_listener(on_connect)
|
2153
|
+
master = master_env.create_master_runner("*", 0)
|
2154
|
+
sleep(0)
|
2155
|
+
worker_env = Environment(user_classes=[TestUser])
|
2156
|
+
worker: WorkerRunner = worker_env.create_worker_runner("127.0.0.1", master.server.port)
|
2157
|
+
|
2158
|
+
with (
|
2159
|
+
mock.patch.object(
|
2160
|
+
worker.environment.events.heartbeat_received,
|
2161
|
+
"fire",
|
2162
|
+
wraps=worker.environment.events.heartbeat_received.fire,
|
2163
|
+
) as worker_heartbeat_received_mock,
|
2164
|
+
mock.patch.object(
|
2165
|
+
master.environment.events.heartbeat_sent,
|
2166
|
+
"fire",
|
2167
|
+
wraps=master.environment.events.heartbeat_sent.fire,
|
2168
|
+
) as master_heartbeat_sent_mock,
|
2169
|
+
):
|
2170
|
+
# give workers time to connect
|
2171
|
+
sleep(0.1)
|
2172
|
+
# issue start command that should trigger TestUsers to be spawned in the Workers
|
2173
|
+
master.start(2, spawn_rate=2)
|
2174
|
+
sleep(0.1)
|
2175
|
+
# check that worker nodes have started locusts
|
2176
|
+
self.assertEqual(2, worker.user_count)
|
2177
|
+
|
2178
|
+
# give time for nodes to send and receive 5 heartbeats, HEARTBEAT_INTERVAL mocked to 1 second, so
|
2179
|
+
# sleep 5 seconds - 1 second that represents the overhead from connecting
|
2180
|
+
sleep(5 - 1)
|
2181
|
+
master.quit()
|
2182
|
+
|
2183
|
+
# make sure users are killed
|
2184
|
+
self.assertEqual(0, worker.user_count)
|
2185
|
+
# make sure events happened correctly
|
2186
|
+
self.assertIn(worker.client_id, worker_connect_events)
|
2187
|
+
|
2188
|
+
timestamp_stop = time.time()
|
2189
|
+
|
2190
|
+
self.assertEqual(worker_heartbeat_received_mock.call_count, 5)
|
2191
|
+
self.assertEqual(master_heartbeat_sent_mock.call_count, 5)
|
2192
|
+
|
2193
|
+
for call_args, call_kwargs in [
|
2194
|
+
*worker_heartbeat_received_mock.call_args_list,
|
2195
|
+
*master_heartbeat_sent_mock.call_args_list,
|
2196
|
+
]:
|
2197
|
+
self.assertEqual(call_args, ()) # args
|
2198
|
+
self.assertEqual(call_kwargs, {"client_id": worker.client_id, "timestamp": mock.ANY}) # kwargs
|
2199
|
+
self.assertGreaterEqual(call_kwargs["timestamp"], timestamp_start[0])
|
2200
|
+
self.assertLessEqual(call_kwargs["timestamp"], timestamp_stop)
|
2201
|
+
|
2202
|
+
def test_usage_monitor_event(self) -> None:
|
2203
|
+
"""
|
2204
|
+
Tests that usage_monitor event is fired during a test
|
2205
|
+
"""
|
2206
|
+
|
2207
|
+
class TestUser(User):
|
2208
|
+
wait_time = constant(0.1)
|
2209
|
+
|
2210
|
+
@task
|
2211
|
+
def noop(self) -> None:
|
2212
|
+
pass
|
2213
|
+
|
2214
|
+
with mock.patch("locust.runners.CPU_MONITOR_INTERVAL", new=1):
|
2215
|
+
# start a Master runner
|
2216
|
+
master_env = Environment(user_classes=[TestUser])
|
2217
|
+
worker_connect_events = []
|
2218
|
+
|
2219
|
+
def on_connect(client_id: str) -> None:
|
2220
|
+
worker_connect_events.append(client_id)
|
2221
|
+
|
2222
|
+
master_env.events.worker_connect.add_listener(on_connect)
|
2223
|
+
master = master_env.create_master_runner("*", 0)
|
2224
|
+
sleep(0)
|
2225
|
+
worker_env = Environment(user_classes=[TestUser])
|
2226
|
+
worker: WorkerRunner = worker_env.create_worker_runner("127.0.0.1", master.server.port)
|
2227
|
+
|
2228
|
+
with (
|
2229
|
+
mock.patch.object(
|
2230
|
+
worker.environment.events.usage_monitor, "fire", wraps=worker.environment.events.usage_monitor.fire
|
2231
|
+
) as worker_usage_monitor_mock,
|
2232
|
+
mock.patch.object(
|
2233
|
+
master.environment.events.usage_monitor, "fire", wraps=master.environment.events.usage_monitor.fire
|
2234
|
+
) as master_usage_monitor_mock,
|
2235
|
+
):
|
2236
|
+
# give workers time to connect
|
2237
|
+
sleep(0.1)
|
2238
|
+
# issue start command that should trigger TestUsers to be spawned in the Workers
|
2239
|
+
master.start(2, spawn_rate=2)
|
2240
|
+
sleep(0.1)
|
2241
|
+
# check that worker nodes have started locusts
|
2242
|
+
self.assertEqual(2, worker.user_count)
|
2243
|
+
|
2244
|
+
# give time for nodes to send 5 usage_monitor events, CPU_MONITOR_INTERVAL mocked to 1 second, so
|
2245
|
+
# sleep 5 seconds
|
2246
|
+
sleep(5)
|
2247
|
+
master.quit()
|
2248
|
+
|
2249
|
+
# make sure users are killed
|
2250
|
+
self.assertEqual(0, worker.user_count)
|
2251
|
+
# make sure events happened correctly
|
2252
|
+
self.assertIn(worker.client_id, worker_connect_events)
|
2253
|
+
|
2254
|
+
self.assertEqual(worker_usage_monitor_mock.call_count, 5)
|
2255
|
+
self.assertEqual(master_usage_monitor_mock.call_count, 5)
|
2256
|
+
|
2257
|
+
for call_args, call_kwargs in master_usage_monitor_mock:
|
2258
|
+
self.assertEqual(call_args, ()) # args
|
2259
|
+
self.assertEqual(
|
2260
|
+
call_kwargs, {"environment": master_env, "cpu_usage": mock.ANY, "memory_usage": mock.ANY}
|
2261
|
+
) # kwargs
|
2262
|
+
self.assertTrue(isinstance(call_kwargs["cpu_usage"], float))
|
2263
|
+
self.assertTrue(isinstance(call_kwargs["memory_usage"], int))
|
2264
|
+
|
2265
|
+
for call_args, call_kwargs in worker_usage_monitor_mock:
|
2266
|
+
self.assertEqual(call_args, ()) # args
|
2267
|
+
self.assertEqual(
|
2268
|
+
call_kwargs, {"environment": worker_env, "cpu_usage": mock.ANY, "memory_usage": mock.ANY}
|
2269
|
+
) # kwargs
|
2270
|
+
self.assertTrue(isinstance(call_kwargs["cpu_usage"], float))
|
2271
|
+
self.assertTrue(isinstance(call_kwargs["memory_usage"], int))
|
2272
|
+
|
2139
2273
|
|
2140
2274
|
class TestMasterRunner(LocustRunnerTestCase):
|
2141
2275
|
def setUp(self):
|