jmeter_perf 1.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +19 -0
- data/.standard.yml +4 -0
- data/CHANGELOG.md +18 -0
- data/DSL.md +235 -0
- data/README.md +24 -0
- data/Rakefile +12 -0
- data/example/Gemfile +39 -0
- data/example/Gemfile.lock +232 -0
- data/example/README.md +3 -0
- data/example/Rakefile +6 -0
- data/example/app/controllers/application_controller.rb +2 -0
- data/example/app/controllers/test_controller.rb +15 -0
- data/example/bin/bundle +109 -0
- data/example/bin/docker-entrypoint +8 -0
- data/example/bin/rails +4 -0
- data/example/bin/rake +4 -0
- data/example/bin/setup +33 -0
- data/example/config/application.rb +44 -0
- data/example/config/boot.rb +3 -0
- data/example/config/credentials.yml.enc +1 -0
- data/example/config/database.yml +25 -0
- data/example/config/environment.rb +5 -0
- data/example/config/environments/development.rb +64 -0
- data/example/config/environments/production.rb +82 -0
- data/example/config/environments/test.rb +61 -0
- data/example/config/initializers/cors.rb +16 -0
- data/example/config/initializers/filter_parameter_logging.rb +8 -0
- data/example/config/initializers/inflections.rb +16 -0
- data/example/config/locales/en.yml +31 -0
- data/example/config/puma.rb +35 -0
- data/example/config/routes.rb +5 -0
- data/example/config.ru +7 -0
- data/example/fast.log +49 -0
- data/example/jmeter.log +28 -0
- data/example/lib/tasks/test.rake +40 -0
- data/example/log/.keep +0 -0
- data/example/public/robots.txt +1 -0
- data/example/random.log +49 -0
- data/example/slow.log +49 -0
- data/example/vendor/.keep +0 -0
- data/lib/Rakefile +4 -0
- data/lib/jmeter_perf/dsl/access_log_sampler.rb +38 -0
- data/lib/jmeter_perf/dsl/aggregate_graph.rb +61 -0
- data/lib/jmeter_perf/dsl/aggregate_report.rb +61 -0
- data/lib/jmeter_perf/dsl/ajp13_sampler.rb +47 -0
- data/lib/jmeter_perf/dsl/assertion_results.rb +61 -0
- data/lib/jmeter_perf/dsl/bean_shell_assertion.rb +34 -0
- data/lib/jmeter_perf/dsl/bean_shell_listener.rb +34 -0
- data/lib/jmeter_perf/dsl/bean_shell_postprocessor.rb +34 -0
- data/lib/jmeter_perf/dsl/bean_shell_preprocessor.rb +34 -0
- data/lib/jmeter_perf/dsl/bean_shell_sampler.rb +34 -0
- data/lib/jmeter_perf/dsl/bean_shell_timer.rb +34 -0
- data/lib/jmeter_perf/dsl/bsf_assertion.rb +34 -0
- data/lib/jmeter_perf/dsl/bsf_listener.rb +34 -0
- data/lib/jmeter_perf/dsl/bsf_postprocessor.rb +34 -0
- data/lib/jmeter_perf/dsl/bsf_preprocessor.rb +34 -0
- data/lib/jmeter_perf/dsl/bsf_sampler.rb +34 -0
- data/lib/jmeter_perf/dsl/bsf_timer.rb +34 -0
- data/lib/jmeter_perf/dsl/compare_assertion.rb +33 -0
- data/lib/jmeter_perf/dsl/comparison_assertion_visualizer.rb +61 -0
- data/lib/jmeter_perf/dsl/constant_throughput_timer.rb +32 -0
- data/lib/jmeter_perf/dsl/constant_timer.rb +31 -0
- data/lib/jmeter_perf/dsl/counter.rb +37 -0
- data/lib/jmeter_perf/dsl/css_jquery_extractor.rb +37 -0
- data/lib/jmeter_perf/dsl/csv_data_set_config.rb +39 -0
- data/lib/jmeter_perf/dsl/debug_postprocessor.rb +34 -0
- data/lib/jmeter_perf/dsl/debug_sampler.rb +33 -0
- data/lib/jmeter_perf/dsl/distribution_graphalpha.rb +61 -0
- data/lib/jmeter_perf/dsl/duration_assertion.rb +31 -0
- data/lib/jmeter_perf/dsl/for_each_controller.rb +33 -0
- data/lib/jmeter_perf/dsl/ftp_request.rb +40 -0
- data/lib/jmeter_perf/dsl/ftp_request_defaults.rb +38 -0
- data/lib/jmeter_perf/dsl/gaussian_random_timer.rb +32 -0
- data/lib/jmeter_perf/dsl/generate_summary_results.rb +29 -0
- data/lib/jmeter_perf/dsl/graph_results.rb +61 -0
- data/lib/jmeter_perf/dsl/html_assertion.rb +36 -0
- data/lib/jmeter_perf/dsl/html_link_parser.rb +29 -0
- data/lib/jmeter_perf/dsl/html_parameter_mask.rb +38 -0
- data/lib/jmeter_perf/dsl/http_authorization_manager.rb +39 -0
- data/lib/jmeter_perf/dsl/http_cache_manager.rb +32 -0
- data/lib/jmeter_perf/dsl/http_cookie_manager.rb +34 -0
- data/lib/jmeter_perf/dsl/http_header_manager.rb +36 -0
- data/lib/jmeter_perf/dsl/http_request.rb +47 -0
- data/lib/jmeter_perf/dsl/http_request_defaults.rb +53 -0
- data/lib/jmeter_perf/dsl/http_url_rewriting_modifier.rb +36 -0
- data/lib/jmeter_perf/dsl/if_controller.rb +33 -0
- data/lib/jmeter_perf/dsl/include_controller.rb +31 -0
- data/lib/jmeter_perf/dsl/j_unit_request.rb +43 -0
- data/lib/jmeter_perf/dsl/java_request.rb +75 -0
- data/lib/jmeter_perf/dsl/java_request_defaults.rb +75 -0
- data/lib/jmeter_perf/dsl/jdbc_connection_configuration.rb +43 -0
- data/lib/jmeter_perf/dsl/jdbc_postprocessor.rb +39 -0
- data/lib/jmeter_perf/dsl/jdbc_preprocessor.rb +39 -0
- data/lib/jmeter_perf/dsl/jdbc_request.rb +39 -0
- data/lib/jmeter_perf/dsl/jms_pointto_point.rb +47 -0
- data/lib/jmeter_perf/dsl/jms_publisher.rb +49 -0
- data/lib/jmeter_perf/dsl/jms_subscriber.rb +41 -0
- data/lib/jmeter_perf/dsl/json_path_postprocessor.rb +33 -0
- data/lib/jmeter_perf/dsl/jsr223_assertion.rb +35 -0
- data/lib/jmeter_perf/dsl/jsr223_listener.rb +35 -0
- data/lib/jmeter_perf/dsl/jsr223_postprocessor.rb +35 -0
- data/lib/jmeter_perf/dsl/jsr223_preprocessor.rb +35 -0
- data/lib/jmeter_perf/dsl/jsr223_sampler.rb +35 -0
- data/lib/jmeter_perf/dsl/jsr223_timer.rb +35 -0
- data/lib/jmeter_perf/dsl/keystore_configuration.rb +34 -0
- data/lib/jmeter_perf/dsl/ldap_extended_request.rb +48 -0
- data/lib/jmeter_perf/dsl/ldap_extended_request_defaults.rb +48 -0
- data/lib/jmeter_perf/dsl/ldap_request.rb +41 -0
- data/lib/jmeter_perf/dsl/ldap_request_defaults.rb +45 -0
- data/lib/jmeter_perf/dsl/login_config_element.rb +32 -0
- data/lib/jmeter_perf/dsl/loop_controller.rb +32 -0
- data/lib/jmeter_perf/dsl/mail_reader_sampler.rb +43 -0
- data/lib/jmeter_perf/dsl/mailer_visualizer.rb +70 -0
- data/lib/jmeter_perf/dsl/md5_hex_assertion.rb +31 -0
- data/lib/jmeter_perf/dsl/module_controller.rb +31 -0
- data/lib/jmeter_perf/dsl/monitor_results.rb +61 -0
- data/lib/jmeter_perf/dsl/once_only_controller.rb +29 -0
- data/lib/jmeter_perf/dsl/os_process_sampler.rb +40 -0
- data/lib/jmeter_perf/dsl/poisson_random_timer.rb +32 -0
- data/lib/jmeter_perf/dsl/random_controller.rb +31 -0
- data/lib/jmeter_perf/dsl/random_order_controller.rb +29 -0
- data/lib/jmeter_perf/dsl/random_variable.rb +36 -0
- data/lib/jmeter_perf/dsl/recording_controller.rb +29 -0
- data/lib/jmeter_perf/dsl/reg_ex_user_parameters.rb +33 -0
- data/lib/jmeter_perf/dsl/regular_expression_extractor.rb +38 -0
- data/lib/jmeter_perf/dsl/response_assertion.rb +37 -0
- data/lib/jmeter_perf/dsl/response_time_graph.rb +61 -0
- data/lib/jmeter_perf/dsl/result_status_action_handler.rb +31 -0
- data/lib/jmeter_perf/dsl/runtime_controller.rb +31 -0
- data/lib/jmeter_perf/dsl/save_responses_to_a_file.rb +35 -0
- data/lib/jmeter_perf/dsl/simple_config_element.rb +29 -0
- data/lib/jmeter_perf/dsl/simple_controller.rb +29 -0
- data/lib/jmeter_perf/dsl/simple_data_writer.rb +61 -0
- data/lib/jmeter_perf/dsl/smime_assertion.rb +41 -0
- data/lib/jmeter_perf/dsl/smtp_sampler.rb +57 -0
- data/lib/jmeter_perf/dsl/soap_xml_rpc_request.rb +39 -0
- data/lib/jmeter_perf/dsl/spline_visualizer.rb +61 -0
- data/lib/jmeter_perf/dsl/summary_report.rb +61 -0
- data/lib/jmeter_perf/dsl/switch_controller.rb +31 -0
- data/lib/jmeter_perf/dsl/synchronizing_timer.rb +32 -0
- data/lib/jmeter_perf/dsl/tcp_sampler.rb +39 -0
- data/lib/jmeter_perf/dsl/tcp_sampler_config.rb +37 -0
- data/lib/jmeter_perf/dsl/test_action.rb +33 -0
- data/lib/jmeter_perf/dsl/test_fragment.rb +29 -0
- data/lib/jmeter_perf/dsl/test_plan.rb +37 -0
- data/lib/jmeter_perf/dsl/thread_group.rb +43 -0
- data/lib/jmeter_perf/dsl/throughput_controller.rb +38 -0
- data/lib/jmeter_perf/dsl/transaction_controller.rb +32 -0
- data/lib/jmeter_perf/dsl/uniform_random_timer.rb +32 -0
- data/lib/jmeter_perf/dsl/user_defined_variables.rb +39 -0
- data/lib/jmeter_perf/dsl/user_parameters.rb +36 -0
- data/lib/jmeter_perf/dsl/view_results_in_table.rb +61 -0
- data/lib/jmeter_perf/dsl/view_results_tree.rb +61 -0
- data/lib/jmeter_perf/dsl/while_controller.rb +31 -0
- data/lib/jmeter_perf/dsl/x_path_assertion.rb +37 -0
- data/lib/jmeter_perf/dsl/x_path_extractor.rb +37 -0
- data/lib/jmeter_perf/dsl/xml_assertion.rb +29 -0
- data/lib/jmeter_perf/dsl/xml_schema_assertion.rb +31 -0
- data/lib/jmeter_perf/extend/assertions/response_assertion.rb +38 -0
- data/lib/jmeter_perf/extend/config_elements/header_manager.rb +13 -0
- data/lib/jmeter_perf/extend/config_elements/http_cache_manager.rb +12 -0
- data/lib/jmeter_perf/extend/config_elements/http_cookie_manager.rb +39 -0
- data/lib/jmeter_perf/extend/config_elements/http_request_defaults.rb +55 -0
- data/lib/jmeter_perf/extend/config_elements/user_defined_variables.rb +13 -0
- data/lib/jmeter_perf/extend/config_elements/user_parameters.rb +31 -0
- data/lib/jmeter_perf/extend/controllers/foreach_controller.rb +31 -0
- data/lib/jmeter_perf/extend/controllers/loop_controller.rb +11 -0
- data/lib/jmeter_perf/extend/controllers/module_controller.rb +26 -0
- data/lib/jmeter_perf/extend/controllers/throughput_controller.rb +15 -0
- data/lib/jmeter_perf/extend/controllers/transaction_controller.rb +14 -0
- data/lib/jmeter_perf/extend/misc/exists.rb +13 -0
- data/lib/jmeter_perf/extend/misc/rsync.rb +24 -0
- data/lib/jmeter_perf/extend/misc/uuid.rb +12 -0
- data/lib/jmeter_perf/extend/misc/with_helpers.rb +27 -0
- data/lib/jmeter_perf/extend/plugins/jmeter_plugins.rb +124 -0
- data/lib/jmeter_perf/extend/processors/extract.rb +27 -0
- data/lib/jmeter_perf/extend/processors/regular_expression_extractor.rb +27 -0
- data/lib/jmeter_perf/extend/samplers/http_request.rb +66 -0
- data/lib/jmeter_perf/extend/samplers/jms_pointtopoint.rb +23 -0
- data/lib/jmeter_perf/extend/samplers/soapxmlrpc_request.rb +10 -0
- data/lib/jmeter_perf/extend/threads/thread_group.rb +19 -0
- data/lib/jmeter_perf/extend/timers/constant_throughput_timer.rb +11 -0
- data/lib/jmeter_perf/extend/timers/random_timer.rb +14 -0
- data/lib/jmeter_perf/helpers/dsl_generator.rb +157 -0
- data/lib/jmeter_perf/helpers/fallback_content_proxy.rb +96 -0
- data/lib/jmeter_perf/helpers/helper.rb +63 -0
- data/lib/jmeter_perf/helpers/parser.rb +143 -0
- data/lib/jmeter_perf/helpers/running_statistics.rb +62 -0
- data/lib/jmeter_perf/helpers/string.rb +60 -0
- data/lib/jmeter_perf/helpers/user-agents.rb +42 -0
- data/lib/jmeter_perf/plugins/active_threads_over_time.rb +59 -0
- data/lib/jmeter_perf/plugins/composite_graph.rb +77 -0
- data/lib/jmeter_perf/plugins/console_status_logger.rb +19 -0
- data/lib/jmeter_perf/plugins/dummy_sampler.rb +30 -0
- data/lib/jmeter_perf/plugins/jmx_collector.rb +74 -0
- data/lib/jmeter_perf/plugins/json_path_assertion.rb +23 -0
- data/lib/jmeter_perf/plugins/json_path_extractor.rb +22 -0
- data/lib/jmeter_perf/plugins/latencies_over_time.rb +53 -0
- data/lib/jmeter_perf/plugins/loadosophia_uploader.rb +66 -0
- data/lib/jmeter_perf/plugins/perfmon_collector.rb +87 -0
- data/lib/jmeter_perf/plugins/redis_data_set.rb +43 -0
- data/lib/jmeter_perf/plugins/response_codes_per_second.rb +53 -0
- data/lib/jmeter_perf/plugins/response_times_distribution.rb +53 -0
- data/lib/jmeter_perf/plugins/response_times_over_time.rb +53 -0
- data/lib/jmeter_perf/plugins/response_times_percentiles.rb +54 -0
- data/lib/jmeter_perf/plugins/stepping_thread_group.rb +34 -0
- data/lib/jmeter_perf/plugins/transactions_per_second.rb +53 -0
- data/lib/jmeter_perf/plugins/ultimate_thread_group.rb +28 -0
- data/lib/jmeter_perf/plugins/variable_throughput_timer.rb +35 -0
- data/lib/jmeter_perf/report/comparator.rb +258 -0
- data/lib/jmeter_perf/report/summary.rb +268 -0
- data/lib/jmeter_perf/tasks/dsl.rake +19 -0
- data/lib/jmeter_perf/version.rb +5 -0
- data/lib/jmeter_perf/views/report_template.html.erb +114 -0
- data/lib/jmeter_perf.rb +183 -0
- data/lib/specifications/idl.xml +1494 -0
- data/sig/jmeter_perf.rbs +195 -0
- data/sorbet/config +5 -0
- data/sorbet/rbi/annotations/.gitattributes +1 -0
- data/sorbet/rbi/annotations/rainbow.rbi +269 -0
- data/sorbet/rbi/gems/.gitattributes +1 -0
- data/sorbet/rbi/gems/ast@2.4.2.rbi +585 -0
- data/sorbet/rbi/gems/bump@0.10.0.rbi +169 -0
- data/sorbet/rbi/gems/byebug@11.1.3.rbi +3607 -0
- data/sorbet/rbi/gems/coderay@1.1.3.rbi +3427 -0
- data/sorbet/rbi/gems/diff-lcs@1.5.1.rbi +1131 -0
- data/sorbet/rbi/gems/docile@1.4.1.rbi +377 -0
- data/sorbet/rbi/gems/erubi@1.13.0.rbi +150 -0
- data/sorbet/rbi/gems/json@2.7.2.rbi +1562 -0
- data/sorbet/rbi/gems/language_server-protocol@3.17.0.3.rbi +14238 -0
- data/sorbet/rbi/gems/lint_roller@1.1.0.rbi +240 -0
- data/sorbet/rbi/gems/method_source@1.1.0.rbi +304 -0
- data/sorbet/rbi/gems/netrc@0.11.0.rbi +159 -0
- data/sorbet/rbi/gems/nokogiri@1.16.7.rbi +7311 -0
- data/sorbet/rbi/gems/parallel@1.26.3.rbi +291 -0
- data/sorbet/rbi/gems/parser@3.3.5.0.rbi +5519 -0
- data/sorbet/rbi/gems/prism@1.2.0.rbi +39085 -0
- data/sorbet/rbi/gems/pry-byebug@3.10.1.rbi +1151 -0
- data/sorbet/rbi/gems/pry@0.14.2.rbi +10076 -0
- data/sorbet/rbi/gems/racc@1.8.1.rbi +162 -0
- data/sorbet/rbi/gems/rainbow@3.1.1.rbi +403 -0
- data/sorbet/rbi/gems/rake@13.2.1.rbi +3074 -0
- data/sorbet/rbi/gems/rbi@0.2.1.rbi +4535 -0
- data/sorbet/rbi/gems/rbtree3@0.7.1.rbi +9 -0
- data/sorbet/rbi/gems/regexp_parser@2.9.2.rbi +3772 -0
- data/sorbet/rbi/gems/rexml@3.3.8.rbi +4858 -0
- data/sorbet/rbi/gems/rspec-core@3.13.1.rbi +11132 -0
- data/sorbet/rbi/gems/rspec-expectations@3.13.3.rbi +8183 -0
- data/sorbet/rbi/gems/rspec-mocks@3.13.1.rbi +5341 -0
- data/sorbet/rbi/gems/rspec-support@3.13.1.rbi +1630 -0
- data/sorbet/rbi/gems/rspec@3.13.0.rbi +83 -0
- data/sorbet/rbi/gems/rubocop-ast@1.32.3.rbi +7054 -0
- data/sorbet/rbi/gems/rubocop-performance@1.21.1.rbi +9 -0
- data/sorbet/rbi/gems/rubocop@1.65.1.rbi +58182 -0
- data/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +1318 -0
- data/sorbet/rbi/gems/simplecov-html@0.13.1.rbi +225 -0
- data/sorbet/rbi/gems/simplecov@0.22.0.rbi +2149 -0
- data/sorbet/rbi/gems/simplecov_json_formatter@0.1.4.rbi +9 -0
- data/sorbet/rbi/gems/spoom@1.5.0.rbi +4932 -0
- data/sorbet/rbi/gems/standard-custom@1.0.2.rbi +9 -0
- data/sorbet/rbi/gems/standard-performance@1.4.0.rbi +9 -0
- data/sorbet/rbi/gems/standard@1.40.0.rbi +926 -0
- data/sorbet/rbi/gems/tapioca@0.16.3.rbi +3596 -0
- data/sorbet/rbi/gems/tdigest@0.2.1.rbi +170 -0
- data/sorbet/rbi/gems/thor@1.3.2.rbi +4378 -0
- data/sorbet/rbi/gems/unicode-display_width@2.6.0.rbi +66 -0
- data/sorbet/rbi/gems/yard-sorbet@0.9.0.rbi +435 -0
- data/sorbet/rbi/gems/yard@0.9.37.rbi +18379 -0
- data/sorbet/rbi/todo.rbi +31 -0
- data/sorbet/tapioca/config.yml +13 -0
- data/sorbet/tapioca/require.rb +15 -0
- data/tasks/dsl.rake +22 -0
- metadata +355 -0
@@ -0,0 +1,157 @@
|
|
1
|
+
require "nokogiri"
|
2
|
+
require "pathname"
|
3
|
+
|
4
|
+
require_relative "string"
|
5
|
+
|
6
|
+
module JmeterPerf
|
7
|
+
module Helpers
|
8
|
+
# The DSLGenerator class generates the DSL methods and files
|
9
|
+
# for use in JMeter performance testing scripts. It uses a JMeter TestPlan (idl.xml)
|
10
|
+
# to generate the methods and files.
|
11
|
+
# @see https://github.com/jlurena/jmeter_perf/wiki/3.-Generating-DSL-Methods
|
12
|
+
class DSLGenerator
|
13
|
+
# Initializes the DSLGenerator.
|
14
|
+
# @param dsl_dir [String] Path to the directory where DSL files will be generated.
|
15
|
+
# @param idl_xml_path [String] Path to the XML file used for generating methods.
|
16
|
+
def initialize(dsl_dir:, idl_xml_path:, document_dsl: true)
|
17
|
+
@document_dsl = document_dsl
|
18
|
+
@dsl_dir = dsl_dir
|
19
|
+
@idl_xml_path = idl_xml_path
|
20
|
+
end
|
21
|
+
|
22
|
+
# Main method to generate DSL files and methods.
|
23
|
+
# It parses the XML, generates methods, documents,
|
24
|
+
# updates RBS files, and creates individual DSL files.
|
25
|
+
# @return [void]
|
26
|
+
def generate
|
27
|
+
results = parse_xml
|
28
|
+
methods = generate_methods(results)
|
29
|
+
|
30
|
+
write_methods_to_dsl_md(methods) if @document_dsl
|
31
|
+
update_rbs(methods) if @document_dsl
|
32
|
+
create_dsl_files(results)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# Parses the XML file specified by the `idl_xml_path` parameter.
|
38
|
+
# @return [Array<Nokogiri::XML::Node>] Array of XML nodes representing valid elements.
|
39
|
+
def parse_xml
|
40
|
+
idl_xml = File.open(@idl_xml_path)
|
41
|
+
doc = Nokogiri::XML(idl_xml.read.gsub(/\n\s+/, ""))
|
42
|
+
results = []
|
43
|
+
|
44
|
+
doc.traverse do |node|
|
45
|
+
if valid_node?(node)
|
46
|
+
results << node
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
results
|
51
|
+
end
|
52
|
+
|
53
|
+
# Checks if a given Nokogiri XML node is valid based on specific criteria.
|
54
|
+
#
|
55
|
+
# A node is considered valid if:
|
56
|
+
# - It is not an instance of Nokogiri::XML::Document.
|
57
|
+
# - It has an attribute named "testclass".
|
58
|
+
# - Its name is not "elementProp".
|
59
|
+
#
|
60
|
+
# @param node [Nokogiri::XML::Node] The XML node to be validated.
|
61
|
+
# @return [Boolean] Returns true if the node is valid, false otherwise.
|
62
|
+
def valid_node?(node)
|
63
|
+
node.class != Nokogiri::XML::Document &&
|
64
|
+
node.attributes["testclass"] &&
|
65
|
+
node.name != "elementProp"
|
66
|
+
end
|
67
|
+
|
68
|
+
# Generates methods based on parsed XML results.
|
69
|
+
# @param results [Array<Nokogiri::XML::Node>] Parsed XML nodes.
|
70
|
+
# @return [Array<Array<String>>] Array of class and method name pairs.
|
71
|
+
def generate_methods(results)
|
72
|
+
results.map do |element|
|
73
|
+
klass = JmeterPerf::Helpers::String.classify(element.attributes["testname"].to_s)
|
74
|
+
method = JmeterPerf::Helpers::String.underscore(klass)
|
75
|
+
[klass, method]
|
76
|
+
end.sort_by(&:first)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Creates individual DSL files based on parsed XML results.
|
80
|
+
# @param results [Array<Nokogiri::XML::Node>] Parsed XML nodes.
|
81
|
+
# @return [void]
|
82
|
+
def create_dsl_files(results)
|
83
|
+
FileUtils.rm_rf(@dsl_dir)
|
84
|
+
FileUtils.mkdir_p(@dsl_dir)
|
85
|
+
|
86
|
+
results.each do |element|
|
87
|
+
klass = JmeterPerf::Helpers::String.classify(element.attributes["testname"].to_s)
|
88
|
+
puts "\tfor Element #{klass}"
|
89
|
+
File.write("#{@dsl_dir}/#{JmeterPerf::Helpers::String.underscore(klass)}.rb", <<~EOC)
|
90
|
+
module JmeterPerf
|
91
|
+
class DSL
|
92
|
+
# DSL method synonymous with the JMeter Element #{klass}
|
93
|
+
# @param params [Hash] Parameters for the #{klass} element (default: `{}`).
|
94
|
+
# @yield block to attach to the #{klass} element
|
95
|
+
# @return [JmeterPerf::#{klass}], a subclass of JmeterPerf::DSL that can be chained with other DSL methods.
|
96
|
+
# @see https://github.com/jlurena/jmeter_perf/wiki/1.-DSL-Documentation##{klass.downcase}
|
97
|
+
def #{JmeterPerf::Helpers::String.underscore(klass)}(params = {}, &)
|
98
|
+
node = #{klass}.new(params)
|
99
|
+
attach_node(node, &)
|
100
|
+
end
|
101
|
+
|
102
|
+
class #{klass}
|
103
|
+
attr_accessor :doc
|
104
|
+
include JmeterPerf::Helpers::XmlDocumentUpdater
|
105
|
+
|
106
|
+
def initialize(params = {})
|
107
|
+
testname = params.is_a?(Array) ? "#{klass}" : (params[:name] || "#{klass}")
|
108
|
+
@doc = Nokogiri::XML(JmeterPerf::Helpers::String.strip_heredoc(
|
109
|
+
<<~EOS
|
110
|
+
#{element.to_xml.gsub(/testname=".+?"/, 'testname="#{testname}"').gsub(/^/, " ")}
|
111
|
+
EOS
|
112
|
+
))
|
113
|
+
update params
|
114
|
+
update_at_xpath params if params.is_a?(Hash) && params[:update_at_xpath]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
EOC
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# Updates the RBS file with method signatures for the DSL methods.
|
124
|
+
# @param methods [Array<Array<String>>] Array of class and method name pairs.
|
125
|
+
# @return [void]
|
126
|
+
def update_rbs(methods)
|
127
|
+
file_path = "sig/jmeter_perf.rbs"
|
128
|
+
replace_regex = /\s*## AUTOGENERATED - DSL methods RBS(.*?)## AUTOGENERATED - DSL methods RBS/m
|
129
|
+
new_content = <<~NEW_CONTENT
|
130
|
+
#{methods.map { |klass, method| " def #{method}: (Hash[Symbol, untyped], &block) -> void" }.join("\n")}
|
131
|
+
NEW_CONTENT
|
132
|
+
|
133
|
+
current_content = File.read(file_path)
|
134
|
+
|
135
|
+
new_file_content = current_content.gsub(replace_regex) do
|
136
|
+
"\n ## AUTOGENERATED - DSL methods RBS\n\n#{new_content}\n ## AUTOGENERATED - DSL methods RBS"
|
137
|
+
end
|
138
|
+
|
139
|
+
File.write(file_path, new_file_content)
|
140
|
+
end
|
141
|
+
|
142
|
+
# Writes the list of generated methods to a markdown file.
|
143
|
+
# @param methods [Array<Array<String>>] Array of class and method name pairs.
|
144
|
+
# @return [void]
|
145
|
+
def write_methods_to_dsl_md(methods)
|
146
|
+
output = []
|
147
|
+
output << "# JmeterPerf::DSL methods"
|
148
|
+
|
149
|
+
methods.each do |klass, method|
|
150
|
+
output << "- #{klass}\n `#{method}`"
|
151
|
+
end
|
152
|
+
|
153
|
+
File.write("DSL.md", output.join("\n"))
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
#
|
2
|
+
# This module provides a proxy class that delegates method calls to a primary receiver object,
|
3
|
+
# and falls back to a secondary object if the primary does not respond to the method.
|
4
|
+
#
|
5
|
+
# @example
|
6
|
+
# primary = PrimaryClass.new
|
7
|
+
# fallback = FallbackClass.new
|
8
|
+
# proxy = JmeterPerf::Helpers::FallbackContextProxy.new(primary, fallback)
|
9
|
+
# proxy.some_method # Will call `some_method` on primary, or fallback if primary does not respond
|
10
|
+
#
|
11
|
+
module JmeterPerf::Helpers
|
12
|
+
class FallbackContextProxy
|
13
|
+
# List of methods that should not be proxied.
|
14
|
+
NON_PROXIED_METHODS = [
|
15
|
+
:__id__,
|
16
|
+
:__send__,
|
17
|
+
:!,
|
18
|
+
:"!=",
|
19
|
+
:==,
|
20
|
+
:equal?,
|
21
|
+
:instance_eval,
|
22
|
+
:instance_variable_get,
|
23
|
+
:instance_variable_set,
|
24
|
+
:instance_variables,
|
25
|
+
:object_id,
|
26
|
+
:remove_instance_variable
|
27
|
+
]
|
28
|
+
|
29
|
+
# List of instance variables that should not be proxied.
|
30
|
+
NON_PROXIED_INSTANCE_VARIABLES = [
|
31
|
+
:@__fallback__,
|
32
|
+
:@__receiver__
|
33
|
+
]
|
34
|
+
|
35
|
+
# Initializes a new FallbackContextProxy.
|
36
|
+
#
|
37
|
+
# @param receiver [Object] the primary object to which method calls are delegated.
|
38
|
+
# @param fallback [Object] the secondary object to which method calls are delegated if the primary does not respond.
|
39
|
+
def initialize(receiver, fallback)
|
40
|
+
@__receiver__ = receiver
|
41
|
+
@__fallback__ = fallback
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns the ID of the primary receiver.
|
45
|
+
#
|
46
|
+
# @return [Object] the ID of the primary receiver.
|
47
|
+
def id
|
48
|
+
@__receiver__.__send__(:id)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Proxies the `sub` method call to the primary receiver or fallback.
|
52
|
+
#
|
53
|
+
# @param args [Array] the arguments to pass to the `sub` method.
|
54
|
+
# @return [Object] the result of the `sub` method call.
|
55
|
+
def sub(...)
|
56
|
+
__proxy_method__(:sub, ...)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns the instance variables of the proxy, excluding non-proxied instance variables.
|
60
|
+
#
|
61
|
+
# @return [Array<Symbol>] the instance variables of the proxy.
|
62
|
+
def instance_variables
|
63
|
+
super.map(&:to_sym) - NON_PROXIED_INSTANCE_VARIABLES
|
64
|
+
end
|
65
|
+
|
66
|
+
# Checks if the proxy responds to a given method.
|
67
|
+
#
|
68
|
+
# @param name [Symbol] the name of the method.
|
69
|
+
# @param include_private [Boolean] whether to include private methods.
|
70
|
+
# @return [Boolean] true if the proxy responds to the method, false otherwise.
|
71
|
+
def respond_to_missing?(name, include_private)
|
72
|
+
__proxy_method__(:respond_to?, name, include_private)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Handles method calls that are not explicitly defined in the proxy.
|
76
|
+
#
|
77
|
+
# @param method [Symbol] the name of the method.
|
78
|
+
# @param args [Array] the arguments to pass to the method.
|
79
|
+
# @return [Object] the result of the method call.
|
80
|
+
def method_missing(method, ...)
|
81
|
+
__proxy_method__(method, ...)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Proxies a method call to the primary receiver or fallback.
|
85
|
+
#
|
86
|
+
# @param method [Symbol] the name of the method.
|
87
|
+
# @param args [Array] the arguments to pass to the method.
|
88
|
+
# @return [Object] the result of the method call.
|
89
|
+
# @raise [NoMethodError] if neither the primary receiver nor the fallback respond to the method.
|
90
|
+
def __proxy_method__(method, ...)
|
91
|
+
@__receiver__.__send__(method.to_sym, ...)
|
92
|
+
rescue NoMethodError
|
93
|
+
@__fallback__.__send__(method.to_sym, ...)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module JmeterPerf::Helpers
|
2
|
+
module XmlDocumentUpdater
|
3
|
+
private
|
4
|
+
|
5
|
+
def update(params)
|
6
|
+
params.delete(:name)
|
7
|
+
enabled_disabled(params)
|
8
|
+
if params.instance_of?(Array)
|
9
|
+
update_collection params
|
10
|
+
else
|
11
|
+
params.each do |name, value|
|
12
|
+
node = @doc.children.xpath("//*[contains(@name,\"#{name}\")]")
|
13
|
+
if value.instance_of?(Nokogiri::XML::Builder)
|
14
|
+
node.first.children = value.doc.at_xpath("//builder").children
|
15
|
+
else
|
16
|
+
node.first.content = value unless node.empty?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def enabled_disabled(params)
|
23
|
+
return unless params.is_a?(Hash)
|
24
|
+
return unless @doc.children.first.attributes["enabled"]
|
25
|
+
@doc.children.first.attributes["enabled"].value = params[:enabled].to_s.empty? ? "true" : "false"
|
26
|
+
end
|
27
|
+
|
28
|
+
def update_at_xpath(params)
|
29
|
+
params[:update_at_xpath].each do |fragment|
|
30
|
+
if fragment[:xpath]
|
31
|
+
@doc.at_xpath(fragment[:xpath]) << fragment[:value]
|
32
|
+
else
|
33
|
+
fragment.each do |xpath, value|
|
34
|
+
@doc.at_xpath(xpath).content = value
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def update_collection(params)
|
41
|
+
elements = @doc.at_xpath("//collectionProp/elementProp")
|
42
|
+
params.each_with_index do |param, index|
|
43
|
+
param.each do |name, value|
|
44
|
+
next unless elements&.element_children
|
45
|
+
element = elements.element_children.xpath("//*[contains(@name,\"#{name}\")]")
|
46
|
+
element.last.content = value
|
47
|
+
end
|
48
|
+
if index != params.size - 1 && elements
|
49
|
+
@doc.at_xpath("//collectionProp") << elements.dup
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def enabled(params)
|
55
|
+
# default to true unless explicitly set to false
|
56
|
+
if params.has_key?(:enabled) && params[:enabled] == false
|
57
|
+
"false"
|
58
|
+
else
|
59
|
+
"true"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require "uri"
|
2
|
+
|
3
|
+
module JmeterPerf::Helpers
|
4
|
+
module Parser
|
5
|
+
private
|
6
|
+
|
7
|
+
def parse_http_request(params)
|
8
|
+
if params[:raw_path]
|
9
|
+
params[:path] = params[:url]
|
10
|
+
parse_url(params)
|
11
|
+
else
|
12
|
+
parse_url(params)
|
13
|
+
params[:fill_in] ||= {}
|
14
|
+
params[:params]&.split("&")&.each do |param|
|
15
|
+
name, value = param.split("=")
|
16
|
+
params[:fill_in][name] ||= []
|
17
|
+
params[:fill_in][name] << value
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
fill_in(params) if params.has_key?(:fill_in)
|
22
|
+
raw_body(params) if params.has_key?(:raw_body)
|
23
|
+
files(params) if params.has_key?(:files)
|
24
|
+
end
|
25
|
+
|
26
|
+
def parse_url(params)
|
27
|
+
return if params[:url].empty?
|
28
|
+
if params[:url] =~ /https?:\/\/\$/ || params[:url][0] == "$"
|
29
|
+
params[:path] = params[:url] # special case for named expressions
|
30
|
+
else
|
31
|
+
uri = parse_uri(params[:url])
|
32
|
+
params[:port] ||= uri.port unless URI.parse(URI::DEFAULT_PARSER.escape(params[:url])).scheme.nil?
|
33
|
+
params[:protocol] ||= uri.scheme unless URI.parse(URI::DEFAULT_PARSER.escape(params[:url])).scheme.nil?
|
34
|
+
params[:domain] ||= uri.host
|
35
|
+
params[:path] ||= uri.path && URI.decode_www_form_component(uri.path)
|
36
|
+
params[:params] ||= uri.query && URI.decode_www_form_component(uri.query)
|
37
|
+
end
|
38
|
+
params.delete(:url)
|
39
|
+
end
|
40
|
+
|
41
|
+
def parse_uri(uri)
|
42
|
+
URI.parse(URI::DEFAULT_PARSER.escape(uri)).scheme.nil? ?
|
43
|
+
URI.parse(URI::DEFAULT_PARSER.escape("http://#{uri}")) :
|
44
|
+
URI.parse(URI::DEFAULT_PARSER.escape(uri))
|
45
|
+
end
|
46
|
+
|
47
|
+
def fill_in(params)
|
48
|
+
params[:update_at_xpath] ||= []
|
49
|
+
params[:update_at_xpath] = params[:fill_in]
|
50
|
+
.each_with_object(params[:update_at_xpath]) do |(name, values), memo|
|
51
|
+
Array(values).each do |value|
|
52
|
+
memo.push({
|
53
|
+
xpath: "//collectionProp",
|
54
|
+
value: Nokogiri::XML(JmeterPerf::Helpers::String.strip_heredoc(
|
55
|
+
<<-EOF
|
56
|
+
<elementProp name="#{name}" elementType="HTTPArgument">
|
57
|
+
<boolProp name="HTTPArgument.always_encode">#{params[:always_encode] ? "true" : false}</boolProp>
|
58
|
+
<stringProp name="Argument.value">#{value}</stringProp>
|
59
|
+
<stringProp name="Argument.metadata">=</stringProp>
|
60
|
+
<boolProp name="HTTPArgument.use_equals">true</boolProp>
|
61
|
+
<stringProp name="Argument.name">#{name}</stringProp>
|
62
|
+
</elementProp>
|
63
|
+
EOF
|
64
|
+
)).children
|
65
|
+
})
|
66
|
+
end
|
67
|
+
end
|
68
|
+
params.delete(:fill_in)
|
69
|
+
end
|
70
|
+
|
71
|
+
def raw_body(params)
|
72
|
+
params[:update_at_xpath] ||= []
|
73
|
+
params[:update_at_xpath].push({
|
74
|
+
xpath: "//HTTPSamplerProxy",
|
75
|
+
value: Nokogiri::XML(JmeterPerf::Helpers::String.strip_heredoc(
|
76
|
+
<<-EOF
|
77
|
+
<boolProp name="HTTPSampler.postBodyRaw">true</boolProp>
|
78
|
+
EOF
|
79
|
+
)).children
|
80
|
+
})
|
81
|
+
|
82
|
+
params[:update_at_xpath].push({
|
83
|
+
xpath: "//collectionProp",
|
84
|
+
value: Nokogiri::XML(JmeterPerf::Helpers::String.strip_heredoc(
|
85
|
+
<<-EOF
|
86
|
+
<elementProp name="" elementType="HTTPArgument">
|
87
|
+
<boolProp name="HTTPArgument.always_encode">false</boolProp>
|
88
|
+
<stringProp name="Argument.value">#{params[:raw_body].encode(xml: :text)}</stringProp>
|
89
|
+
<stringProp name="Argument.metadata">=</stringProp>
|
90
|
+
</elementProp>
|
91
|
+
EOF
|
92
|
+
)).children
|
93
|
+
})
|
94
|
+
params.delete(:raw_body)
|
95
|
+
end
|
96
|
+
|
97
|
+
def files(params)
|
98
|
+
files = params.delete(:files)
|
99
|
+
return if files.empty?
|
100
|
+
x = Nokogiri::XML::Builder.new do |b|
|
101
|
+
b.elementProp(name: "HTTPsampler.Files", elementType: "HTTPFileArgs") {
|
102
|
+
b.collectionProp(name: "HTTPFileArgs.files") {
|
103
|
+
files.each do |f|
|
104
|
+
b.elementProp(name: f[:path], elementType: "HTTPFileArg") {
|
105
|
+
b.stringProp f[:path] || "", name: "File.path"
|
106
|
+
b.stringProp f[:paramname] || "", name: "File.paramname"
|
107
|
+
b.stringProp f[:mimetype] || "", name: "File.mimetype"
|
108
|
+
}
|
109
|
+
end
|
110
|
+
}
|
111
|
+
}
|
112
|
+
end
|
113
|
+
params[:update_at_xpath] ||= []
|
114
|
+
params[:update_at_xpath] << {
|
115
|
+
xpath: "//HTTPSamplerProxy",
|
116
|
+
value: x.doc.root
|
117
|
+
}
|
118
|
+
end
|
119
|
+
|
120
|
+
def parse_test_type(params)
|
121
|
+
case params.keys.first.to_s
|
122
|
+
when "contains"
|
123
|
+
2
|
124
|
+
when "not-contains"
|
125
|
+
6
|
126
|
+
when "matches"
|
127
|
+
1
|
128
|
+
when "not-matches"
|
129
|
+
5
|
130
|
+
when "equals"
|
131
|
+
8
|
132
|
+
when "not-equals"
|
133
|
+
12
|
134
|
+
when "substring"
|
135
|
+
16
|
136
|
+
when "not-substring"
|
137
|
+
20
|
138
|
+
else
|
139
|
+
2
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require "tdigest"
|
2
|
+
|
3
|
+
module JmeterPerf::Helpers
|
4
|
+
# Provides running statistics for a series of numbers, including approximate percentiles and
|
5
|
+
# standard deviation.
|
6
|
+
#
|
7
|
+
# @note This class uses a TDigest data structure to keep statistics "close enough". Accuracy is not guaranteed.
|
8
|
+
class RunningStatistisc
|
9
|
+
# The marker for when to call the compression function on the TDigest structure.
|
10
|
+
COMPRESS_MARKER = 1000
|
11
|
+
|
12
|
+
# @return [Float] the running average of the numbers added
|
13
|
+
attr_reader :avg
|
14
|
+
|
15
|
+
# Initializes a new instance of RunningStatistisc to calculate running statistics.
|
16
|
+
#
|
17
|
+
# @return [RunningStatistisc]
|
18
|
+
def initialize
|
19
|
+
@tdigest = ::TDigest::TDigest.new
|
20
|
+
@count = 0
|
21
|
+
@avg = 0
|
22
|
+
@m2 = 0 # Sum of squares of differences from the avg
|
23
|
+
end
|
24
|
+
|
25
|
+
# Adds a number to the running statistics and updates the average and variance calculations.
|
26
|
+
#
|
27
|
+
# @param num [Float] the number to add to the running statistics
|
28
|
+
# @return [void]
|
29
|
+
def add_number(num)
|
30
|
+
@tdigest.push(num)
|
31
|
+
|
32
|
+
@count += 1
|
33
|
+
delta = num - @avg
|
34
|
+
@avg += delta / @count
|
35
|
+
delta2 = num - @avg
|
36
|
+
@m2 += delta * delta2
|
37
|
+
|
38
|
+
# Compress data every 1000 items to maintain memory efficiency
|
39
|
+
@tdigest.compress! if @count % COMPRESS_MARKER == 0
|
40
|
+
end
|
41
|
+
|
42
|
+
# Retrieves approximate percentiles for the data set based on the requested percentile values.
|
43
|
+
#
|
44
|
+
# @param percentiles [Array<Float>] the requested percentiles (e.g., 0.5 for the 50th percentile)
|
45
|
+
# @return [Array<Float>] an array of calculated percentiles corresponding to the requested values
|
46
|
+
# @example Requesting the 10th, 50th, and 95th percentiles
|
47
|
+
# get_percentiles(0.1, 0.5, 0.95) #=> [some_value_for_10th, some_value_for_50th, some_value_for_95th]
|
48
|
+
def get_percentiles(*percentiles)
|
49
|
+
@tdigest.compress!
|
50
|
+
percentiles.map { |percentile| @tdigest.percentile(percentile) }
|
51
|
+
end
|
52
|
+
|
53
|
+
# Calculates the standard deviation of the numbers added so far.
|
54
|
+
#
|
55
|
+
# @return [Float] the standard deviation, or 0 if fewer than two values have been added
|
56
|
+
def standard_deviation
|
57
|
+
return 0 if @count < 2
|
58
|
+
Math.sqrt(@m2 / (@count - 1))
|
59
|
+
end
|
60
|
+
alias_method :std, :standard_deviation
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module JmeterPerf::Helpers
|
2
|
+
class String
|
3
|
+
class << self
|
4
|
+
# Converts a string to CamelCase.
|
5
|
+
#
|
6
|
+
# @param string [String] the string to be converted.
|
7
|
+
# @return [String] the CamelCase version of the string.
|
8
|
+
def classify(string)
|
9
|
+
camelize(string.gsub(/\s/, "_"))
|
10
|
+
end
|
11
|
+
|
12
|
+
# Converts a string to snake_case.
|
13
|
+
#
|
14
|
+
# @param string [String] the string to be converted.
|
15
|
+
# @return [String] the snake_case version of the string.
|
16
|
+
def underscore(string)
|
17
|
+
string.gsub("::", "/")
|
18
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
19
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
20
|
+
.tr("-", "_")
|
21
|
+
.downcase
|
22
|
+
end
|
23
|
+
|
24
|
+
# Converts a string to CamelCase or camelCase.
|
25
|
+
#
|
26
|
+
# @param str [String] the string to be converted.
|
27
|
+
# @param uppercase_first_letter [Boolean, Symbol] whether to capitalize the first letter or not.
|
28
|
+
# If `:lower`, the first letter will be lowercase.
|
29
|
+
# @return [String] the CamelCase or camelCase version of the string.
|
30
|
+
def camelize(str, uppercase_first_letter = true)
|
31
|
+
string = str.dup
|
32
|
+
# String#camelize takes a symbol (:upper or :lower), so here we also support :lower to keep the methods consistent.
|
33
|
+
if !uppercase_first_letter || uppercase_first_letter == :lower
|
34
|
+
string = string.sub(/^(?:(?=a)b(?=\b|[A-Z_])|\w)/) { |match| match.downcase! || match }
|
35
|
+
elsif string.match?(/\A[a-z\d]*\z/)
|
36
|
+
return string.capitalize
|
37
|
+
else
|
38
|
+
string = string.sub(/^[a-z\d]*/) { |match| match.capitalize || match }
|
39
|
+
end
|
40
|
+
|
41
|
+
string.gsub!(/(?:_|(\/))([a-z\d]*)/i) do
|
42
|
+
word = $2
|
43
|
+
substituted = word.capitalize! || word
|
44
|
+
($1) ? "_#{substituted}" : substituted
|
45
|
+
end
|
46
|
+
|
47
|
+
string.gsub!(/[^a-zA-Z0-9]/, "")
|
48
|
+
string
|
49
|
+
end
|
50
|
+
|
51
|
+
# Strips leading whitespace from each line that is the same as the amount of whitespace on the first line.
|
52
|
+
#
|
53
|
+
# @param string [String] the string to be stripped of leading whitespace.
|
54
|
+
# @return [String] the string with leading whitespace removed.
|
55
|
+
def strip_heredoc(string)
|
56
|
+
string.gsub(/^#{string[/\A\s*/]}/, "")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# This module provides a collection of common user-agent strings for various devices and browsers.
|
2
|
+
# It allows retrieval of user-agent strings based on device type.
|
3
|
+
module JmeterPerf::Helpers
|
4
|
+
module UserAgent
|
5
|
+
# A hash containing user-agent strings for common devices and browsers.
|
6
|
+
# @return [Hash<Symbol, String>] the user-agent strings for various devices and browsers.
|
7
|
+
COMMON_DEVICES = {
|
8
|
+
# User-agent string for iPhone
|
9
|
+
iphone: "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1",
|
10
|
+
# User-agent string for iPod
|
11
|
+
ipod: "Mozilla/5.0 (iPod touch; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1",
|
12
|
+
# User-agent string for iPad
|
13
|
+
ipad: "Mozilla/5.0 (iPad; CPU OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1",
|
14
|
+
# User-agent string for Safari on macOS
|
15
|
+
safari_osx: "Mozilla/5.0 (Macintosh; Intel Mac OS X 13_0) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Safari/605.1.15",
|
16
|
+
# User-agent string for Safari on Windows
|
17
|
+
safari_win: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.188",
|
18
|
+
# User-agent string for Edge
|
19
|
+
edge: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.188",
|
20
|
+
# User-agent string for Chrome on macOS
|
21
|
+
chrome_osx: "Mozilla/5.0 (Macintosh; Intel Mac OS X 13_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36",
|
22
|
+
# User-agent string for Chrome on Windows
|
23
|
+
chrome_win: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36",
|
24
|
+
# User-agent string for Firefox on macOS
|
25
|
+
ff_osx: "Mozilla/5.0 (Macintosh; Intel Mac OS X 13.0; rv:115.0) Gecko/20100101 Firefox/115.0",
|
26
|
+
# User-agent string for Firefox on Windows
|
27
|
+
ff_win: "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:115.0) Gecko/20100101 Firefox/115.0",
|
28
|
+
# User-agent string for Opera on macOS
|
29
|
+
opera_osx: "Mozilla/5.0 (Macintosh; Intel Mac OS X 13.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 OPR/102.0.0.0",
|
30
|
+
# User-agent string for Opera on Windows
|
31
|
+
opera_win: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 OPR/102.0.0.0"
|
32
|
+
}
|
33
|
+
|
34
|
+
# Retrieves the user-agent string for the specified device.
|
35
|
+
#
|
36
|
+
# @param device [Symbol] the device type for which to retrieve the user-agent string.
|
37
|
+
# @return [String] the user-agent string for the specified device, or the default Chrome on macOS user-agent string if the device is not found.
|
38
|
+
def self.string(device)
|
39
|
+
COMMON_DEVICES[device] || COMMON_DEVICES[:chrome_osx]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module JmeterPerf
|
2
|
+
module Plugins
|
3
|
+
class ActiveThreadsOverTime
|
4
|
+
attr_accessor :doc
|
5
|
+
include JmeterPerf::Helpers::XmlDocumentUpdater
|
6
|
+
def initialize(params = {})
|
7
|
+
testname = params.is_a?(Array) ? "ActiveThreadsOverTime" : (params[:name] || "ActiveThreadsOverTime")
|
8
|
+
@doc = Nokogiri::XML(
|
9
|
+
JmeterPerf::Helpers::String.strip_heredoc(
|
10
|
+
<<-XML
|
11
|
+
<kg.apc.jmeter.vizualizers.CorrectedResultCollector guiclass="kg.apc.jmeter.vizualizers.ThreadsStateOverTimeGui" testclass="kg.apc.jmeter.vizualizers.CorrectedResultCollector" testname="#{testname}" enabled="true">
|
12
|
+
<boolProp name="ResultCollector.error_logging">false</boolProp>
|
13
|
+
<objProp>
|
14
|
+
<name>saveConfig</name>
|
15
|
+
<value class="SampleSaveConfiguration">
|
16
|
+
<time>true</time>
|
17
|
+
<latency>true</latency>
|
18
|
+
<timestamp>true</timestamp>
|
19
|
+
<success>true</success>
|
20
|
+
<label>true</label>
|
21
|
+
<code>true</code>
|
22
|
+
<message>false</message>
|
23
|
+
<threadName>true</threadName>
|
24
|
+
<dataType>false</dataType>
|
25
|
+
<encoding>false</encoding>
|
26
|
+
<assertions>false</assertions>
|
27
|
+
<subresults>false</subresults>
|
28
|
+
<responseData>false</responseData>
|
29
|
+
<samplerData>false</samplerData>
|
30
|
+
<xml>false</xml>
|
31
|
+
<fieldNames>false</fieldNames>
|
32
|
+
<responseHeaders>false</responseHeaders>
|
33
|
+
<requestHeaders>false</requestHeaders>
|
34
|
+
<responseDataOnError>false</responseDataOnError>
|
35
|
+
<saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
|
36
|
+
<assertionsResultsToSave>0</assertionsResultsToSave>
|
37
|
+
<bytes>true</bytes>
|
38
|
+
<threadCounts>true</threadCounts>
|
39
|
+
<sampleCount>true</sampleCount>
|
40
|
+
</value>
|
41
|
+
</objProp>
|
42
|
+
<stringProp name="filename"></stringProp>
|
43
|
+
<longProp name="interval_grouping">500</longProp>
|
44
|
+
<boolProp name="graph_aggregated">false</boolProp>
|
45
|
+
<stringProp name="include_sample_labels"></stringProp>
|
46
|
+
<stringProp name="exclude_sample_labels"></stringProp>
|
47
|
+
<stringProp name="start_offset"></stringProp>
|
48
|
+
<stringProp name="end_offset"></stringProp>
|
49
|
+
<boolProp name="include_checkbox_state">false</boolProp>
|
50
|
+
<boolProp name="exclude_checkbox_state">false</boolProp>
|
51
|
+
</kg.apc.jmeter.vizualizers.CorrectedResultCollector>
|
52
|
+
XML
|
53
|
+
)
|
54
|
+
)
|
55
|
+
update params
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|