jmeter_perf 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (275) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +19 -0
  4. data/.standard.yml +4 -0
  5. data/CHANGELOG.md +18 -0
  6. data/DSL.md +235 -0
  7. data/README.md +24 -0
  8. data/Rakefile +12 -0
  9. data/example/Gemfile +39 -0
  10. data/example/Gemfile.lock +232 -0
  11. data/example/README.md +3 -0
  12. data/example/Rakefile +6 -0
  13. data/example/app/controllers/application_controller.rb +2 -0
  14. data/example/app/controllers/test_controller.rb +15 -0
  15. data/example/bin/bundle +109 -0
  16. data/example/bin/docker-entrypoint +8 -0
  17. data/example/bin/rails +4 -0
  18. data/example/bin/rake +4 -0
  19. data/example/bin/setup +33 -0
  20. data/example/config/application.rb +44 -0
  21. data/example/config/boot.rb +3 -0
  22. data/example/config/credentials.yml.enc +1 -0
  23. data/example/config/database.yml +25 -0
  24. data/example/config/environment.rb +5 -0
  25. data/example/config/environments/development.rb +64 -0
  26. data/example/config/environments/production.rb +82 -0
  27. data/example/config/environments/test.rb +61 -0
  28. data/example/config/initializers/cors.rb +16 -0
  29. data/example/config/initializers/filter_parameter_logging.rb +8 -0
  30. data/example/config/initializers/inflections.rb +16 -0
  31. data/example/config/locales/en.yml +31 -0
  32. data/example/config/puma.rb +35 -0
  33. data/example/config/routes.rb +5 -0
  34. data/example/config.ru +7 -0
  35. data/example/fast.log +49 -0
  36. data/example/jmeter.log +28 -0
  37. data/example/lib/tasks/test.rake +40 -0
  38. data/example/log/.keep +0 -0
  39. data/example/public/robots.txt +1 -0
  40. data/example/random.log +49 -0
  41. data/example/slow.log +49 -0
  42. data/example/vendor/.keep +0 -0
  43. data/lib/Rakefile +4 -0
  44. data/lib/jmeter_perf/dsl/access_log_sampler.rb +38 -0
  45. data/lib/jmeter_perf/dsl/aggregate_graph.rb +61 -0
  46. data/lib/jmeter_perf/dsl/aggregate_report.rb +61 -0
  47. data/lib/jmeter_perf/dsl/ajp13_sampler.rb +47 -0
  48. data/lib/jmeter_perf/dsl/assertion_results.rb +61 -0
  49. data/lib/jmeter_perf/dsl/bean_shell_assertion.rb +34 -0
  50. data/lib/jmeter_perf/dsl/bean_shell_listener.rb +34 -0
  51. data/lib/jmeter_perf/dsl/bean_shell_postprocessor.rb +34 -0
  52. data/lib/jmeter_perf/dsl/bean_shell_preprocessor.rb +34 -0
  53. data/lib/jmeter_perf/dsl/bean_shell_sampler.rb +34 -0
  54. data/lib/jmeter_perf/dsl/bean_shell_timer.rb +34 -0
  55. data/lib/jmeter_perf/dsl/bsf_assertion.rb +34 -0
  56. data/lib/jmeter_perf/dsl/bsf_listener.rb +34 -0
  57. data/lib/jmeter_perf/dsl/bsf_postprocessor.rb +34 -0
  58. data/lib/jmeter_perf/dsl/bsf_preprocessor.rb +34 -0
  59. data/lib/jmeter_perf/dsl/bsf_sampler.rb +34 -0
  60. data/lib/jmeter_perf/dsl/bsf_timer.rb +34 -0
  61. data/lib/jmeter_perf/dsl/compare_assertion.rb +33 -0
  62. data/lib/jmeter_perf/dsl/comparison_assertion_visualizer.rb +61 -0
  63. data/lib/jmeter_perf/dsl/constant_throughput_timer.rb +32 -0
  64. data/lib/jmeter_perf/dsl/constant_timer.rb +31 -0
  65. data/lib/jmeter_perf/dsl/counter.rb +37 -0
  66. data/lib/jmeter_perf/dsl/css_jquery_extractor.rb +37 -0
  67. data/lib/jmeter_perf/dsl/csv_data_set_config.rb +39 -0
  68. data/lib/jmeter_perf/dsl/debug_postprocessor.rb +34 -0
  69. data/lib/jmeter_perf/dsl/debug_sampler.rb +33 -0
  70. data/lib/jmeter_perf/dsl/distribution_graphalpha.rb +61 -0
  71. data/lib/jmeter_perf/dsl/duration_assertion.rb +31 -0
  72. data/lib/jmeter_perf/dsl/for_each_controller.rb +33 -0
  73. data/lib/jmeter_perf/dsl/ftp_request.rb +40 -0
  74. data/lib/jmeter_perf/dsl/ftp_request_defaults.rb +38 -0
  75. data/lib/jmeter_perf/dsl/gaussian_random_timer.rb +32 -0
  76. data/lib/jmeter_perf/dsl/generate_summary_results.rb +29 -0
  77. data/lib/jmeter_perf/dsl/graph_results.rb +61 -0
  78. data/lib/jmeter_perf/dsl/html_assertion.rb +36 -0
  79. data/lib/jmeter_perf/dsl/html_link_parser.rb +29 -0
  80. data/lib/jmeter_perf/dsl/html_parameter_mask.rb +38 -0
  81. data/lib/jmeter_perf/dsl/http_authorization_manager.rb +39 -0
  82. data/lib/jmeter_perf/dsl/http_cache_manager.rb +32 -0
  83. data/lib/jmeter_perf/dsl/http_cookie_manager.rb +34 -0
  84. data/lib/jmeter_perf/dsl/http_header_manager.rb +36 -0
  85. data/lib/jmeter_perf/dsl/http_request.rb +47 -0
  86. data/lib/jmeter_perf/dsl/http_request_defaults.rb +53 -0
  87. data/lib/jmeter_perf/dsl/http_url_rewriting_modifier.rb +36 -0
  88. data/lib/jmeter_perf/dsl/if_controller.rb +33 -0
  89. data/lib/jmeter_perf/dsl/include_controller.rb +31 -0
  90. data/lib/jmeter_perf/dsl/j_unit_request.rb +43 -0
  91. data/lib/jmeter_perf/dsl/java_request.rb +75 -0
  92. data/lib/jmeter_perf/dsl/java_request_defaults.rb +75 -0
  93. data/lib/jmeter_perf/dsl/jdbc_connection_configuration.rb +43 -0
  94. data/lib/jmeter_perf/dsl/jdbc_postprocessor.rb +39 -0
  95. data/lib/jmeter_perf/dsl/jdbc_preprocessor.rb +39 -0
  96. data/lib/jmeter_perf/dsl/jdbc_request.rb +39 -0
  97. data/lib/jmeter_perf/dsl/jms_pointto_point.rb +47 -0
  98. data/lib/jmeter_perf/dsl/jms_publisher.rb +49 -0
  99. data/lib/jmeter_perf/dsl/jms_subscriber.rb +41 -0
  100. data/lib/jmeter_perf/dsl/json_path_postprocessor.rb +33 -0
  101. data/lib/jmeter_perf/dsl/jsr223_assertion.rb +35 -0
  102. data/lib/jmeter_perf/dsl/jsr223_listener.rb +35 -0
  103. data/lib/jmeter_perf/dsl/jsr223_postprocessor.rb +35 -0
  104. data/lib/jmeter_perf/dsl/jsr223_preprocessor.rb +35 -0
  105. data/lib/jmeter_perf/dsl/jsr223_sampler.rb +35 -0
  106. data/lib/jmeter_perf/dsl/jsr223_timer.rb +35 -0
  107. data/lib/jmeter_perf/dsl/keystore_configuration.rb +34 -0
  108. data/lib/jmeter_perf/dsl/ldap_extended_request.rb +48 -0
  109. data/lib/jmeter_perf/dsl/ldap_extended_request_defaults.rb +48 -0
  110. data/lib/jmeter_perf/dsl/ldap_request.rb +41 -0
  111. data/lib/jmeter_perf/dsl/ldap_request_defaults.rb +45 -0
  112. data/lib/jmeter_perf/dsl/login_config_element.rb +32 -0
  113. data/lib/jmeter_perf/dsl/loop_controller.rb +32 -0
  114. data/lib/jmeter_perf/dsl/mail_reader_sampler.rb +43 -0
  115. data/lib/jmeter_perf/dsl/mailer_visualizer.rb +70 -0
  116. data/lib/jmeter_perf/dsl/md5_hex_assertion.rb +31 -0
  117. data/lib/jmeter_perf/dsl/module_controller.rb +31 -0
  118. data/lib/jmeter_perf/dsl/monitor_results.rb +61 -0
  119. data/lib/jmeter_perf/dsl/once_only_controller.rb +29 -0
  120. data/lib/jmeter_perf/dsl/os_process_sampler.rb +40 -0
  121. data/lib/jmeter_perf/dsl/poisson_random_timer.rb +32 -0
  122. data/lib/jmeter_perf/dsl/random_controller.rb +31 -0
  123. data/lib/jmeter_perf/dsl/random_order_controller.rb +29 -0
  124. data/lib/jmeter_perf/dsl/random_variable.rb +36 -0
  125. data/lib/jmeter_perf/dsl/recording_controller.rb +29 -0
  126. data/lib/jmeter_perf/dsl/reg_ex_user_parameters.rb +33 -0
  127. data/lib/jmeter_perf/dsl/regular_expression_extractor.rb +38 -0
  128. data/lib/jmeter_perf/dsl/response_assertion.rb +37 -0
  129. data/lib/jmeter_perf/dsl/response_time_graph.rb +61 -0
  130. data/lib/jmeter_perf/dsl/result_status_action_handler.rb +31 -0
  131. data/lib/jmeter_perf/dsl/runtime_controller.rb +31 -0
  132. data/lib/jmeter_perf/dsl/save_responses_to_a_file.rb +35 -0
  133. data/lib/jmeter_perf/dsl/simple_config_element.rb +29 -0
  134. data/lib/jmeter_perf/dsl/simple_controller.rb +29 -0
  135. data/lib/jmeter_perf/dsl/simple_data_writer.rb +61 -0
  136. data/lib/jmeter_perf/dsl/smime_assertion.rb +41 -0
  137. data/lib/jmeter_perf/dsl/smtp_sampler.rb +57 -0
  138. data/lib/jmeter_perf/dsl/soap_xml_rpc_request.rb +39 -0
  139. data/lib/jmeter_perf/dsl/spline_visualizer.rb +61 -0
  140. data/lib/jmeter_perf/dsl/summary_report.rb +61 -0
  141. data/lib/jmeter_perf/dsl/switch_controller.rb +31 -0
  142. data/lib/jmeter_perf/dsl/synchronizing_timer.rb +32 -0
  143. data/lib/jmeter_perf/dsl/tcp_sampler.rb +39 -0
  144. data/lib/jmeter_perf/dsl/tcp_sampler_config.rb +37 -0
  145. data/lib/jmeter_perf/dsl/test_action.rb +33 -0
  146. data/lib/jmeter_perf/dsl/test_fragment.rb +29 -0
  147. data/lib/jmeter_perf/dsl/test_plan.rb +37 -0
  148. data/lib/jmeter_perf/dsl/thread_group.rb +43 -0
  149. data/lib/jmeter_perf/dsl/throughput_controller.rb +38 -0
  150. data/lib/jmeter_perf/dsl/transaction_controller.rb +32 -0
  151. data/lib/jmeter_perf/dsl/uniform_random_timer.rb +32 -0
  152. data/lib/jmeter_perf/dsl/user_defined_variables.rb +39 -0
  153. data/lib/jmeter_perf/dsl/user_parameters.rb +36 -0
  154. data/lib/jmeter_perf/dsl/view_results_in_table.rb +61 -0
  155. data/lib/jmeter_perf/dsl/view_results_tree.rb +61 -0
  156. data/lib/jmeter_perf/dsl/while_controller.rb +31 -0
  157. data/lib/jmeter_perf/dsl/x_path_assertion.rb +37 -0
  158. data/lib/jmeter_perf/dsl/x_path_extractor.rb +37 -0
  159. data/lib/jmeter_perf/dsl/xml_assertion.rb +29 -0
  160. data/lib/jmeter_perf/dsl/xml_schema_assertion.rb +31 -0
  161. data/lib/jmeter_perf/extend/assertions/response_assertion.rb +38 -0
  162. data/lib/jmeter_perf/extend/config_elements/header_manager.rb +13 -0
  163. data/lib/jmeter_perf/extend/config_elements/http_cache_manager.rb +12 -0
  164. data/lib/jmeter_perf/extend/config_elements/http_cookie_manager.rb +39 -0
  165. data/lib/jmeter_perf/extend/config_elements/http_request_defaults.rb +55 -0
  166. data/lib/jmeter_perf/extend/config_elements/user_defined_variables.rb +13 -0
  167. data/lib/jmeter_perf/extend/config_elements/user_parameters.rb +31 -0
  168. data/lib/jmeter_perf/extend/controllers/foreach_controller.rb +31 -0
  169. data/lib/jmeter_perf/extend/controllers/loop_controller.rb +11 -0
  170. data/lib/jmeter_perf/extend/controllers/module_controller.rb +26 -0
  171. data/lib/jmeter_perf/extend/controllers/throughput_controller.rb +15 -0
  172. data/lib/jmeter_perf/extend/controllers/transaction_controller.rb +14 -0
  173. data/lib/jmeter_perf/extend/misc/exists.rb +13 -0
  174. data/lib/jmeter_perf/extend/misc/rsync.rb +24 -0
  175. data/lib/jmeter_perf/extend/misc/uuid.rb +12 -0
  176. data/lib/jmeter_perf/extend/misc/with_helpers.rb +27 -0
  177. data/lib/jmeter_perf/extend/plugins/jmeter_plugins.rb +124 -0
  178. data/lib/jmeter_perf/extend/processors/extract.rb +27 -0
  179. data/lib/jmeter_perf/extend/processors/regular_expression_extractor.rb +27 -0
  180. data/lib/jmeter_perf/extend/samplers/http_request.rb +66 -0
  181. data/lib/jmeter_perf/extend/samplers/jms_pointtopoint.rb +23 -0
  182. data/lib/jmeter_perf/extend/samplers/soapxmlrpc_request.rb +10 -0
  183. data/lib/jmeter_perf/extend/threads/thread_group.rb +19 -0
  184. data/lib/jmeter_perf/extend/timers/constant_throughput_timer.rb +11 -0
  185. data/lib/jmeter_perf/extend/timers/random_timer.rb +14 -0
  186. data/lib/jmeter_perf/helpers/dsl_generator.rb +157 -0
  187. data/lib/jmeter_perf/helpers/fallback_content_proxy.rb +96 -0
  188. data/lib/jmeter_perf/helpers/helper.rb +63 -0
  189. data/lib/jmeter_perf/helpers/parser.rb +143 -0
  190. data/lib/jmeter_perf/helpers/running_statistics.rb +62 -0
  191. data/lib/jmeter_perf/helpers/string.rb +60 -0
  192. data/lib/jmeter_perf/helpers/user-agents.rb +42 -0
  193. data/lib/jmeter_perf/plugins/active_threads_over_time.rb +59 -0
  194. data/lib/jmeter_perf/plugins/composite_graph.rb +77 -0
  195. data/lib/jmeter_perf/plugins/console_status_logger.rb +19 -0
  196. data/lib/jmeter_perf/plugins/dummy_sampler.rb +30 -0
  197. data/lib/jmeter_perf/plugins/jmx_collector.rb +74 -0
  198. data/lib/jmeter_perf/plugins/json_path_assertion.rb +23 -0
  199. data/lib/jmeter_perf/plugins/json_path_extractor.rb +22 -0
  200. data/lib/jmeter_perf/plugins/latencies_over_time.rb +53 -0
  201. data/lib/jmeter_perf/plugins/loadosophia_uploader.rb +66 -0
  202. data/lib/jmeter_perf/plugins/perfmon_collector.rb +87 -0
  203. data/lib/jmeter_perf/plugins/redis_data_set.rb +43 -0
  204. data/lib/jmeter_perf/plugins/response_codes_per_second.rb +53 -0
  205. data/lib/jmeter_perf/plugins/response_times_distribution.rb +53 -0
  206. data/lib/jmeter_perf/plugins/response_times_over_time.rb +53 -0
  207. data/lib/jmeter_perf/plugins/response_times_percentiles.rb +54 -0
  208. data/lib/jmeter_perf/plugins/stepping_thread_group.rb +34 -0
  209. data/lib/jmeter_perf/plugins/transactions_per_second.rb +53 -0
  210. data/lib/jmeter_perf/plugins/ultimate_thread_group.rb +28 -0
  211. data/lib/jmeter_perf/plugins/variable_throughput_timer.rb +35 -0
  212. data/lib/jmeter_perf/report/comparator.rb +258 -0
  213. data/lib/jmeter_perf/report/summary.rb +268 -0
  214. data/lib/jmeter_perf/tasks/dsl.rake +19 -0
  215. data/lib/jmeter_perf/version.rb +5 -0
  216. data/lib/jmeter_perf/views/report_template.html.erb +114 -0
  217. data/lib/jmeter_perf.rb +183 -0
  218. data/lib/specifications/idl.xml +1494 -0
  219. data/sig/jmeter_perf.rbs +195 -0
  220. data/sorbet/config +5 -0
  221. data/sorbet/rbi/annotations/.gitattributes +1 -0
  222. data/sorbet/rbi/annotations/rainbow.rbi +269 -0
  223. data/sorbet/rbi/gems/.gitattributes +1 -0
  224. data/sorbet/rbi/gems/ast@2.4.2.rbi +585 -0
  225. data/sorbet/rbi/gems/bump@0.10.0.rbi +169 -0
  226. data/sorbet/rbi/gems/byebug@11.1.3.rbi +3607 -0
  227. data/sorbet/rbi/gems/coderay@1.1.3.rbi +3427 -0
  228. data/sorbet/rbi/gems/diff-lcs@1.5.1.rbi +1131 -0
  229. data/sorbet/rbi/gems/docile@1.4.1.rbi +377 -0
  230. data/sorbet/rbi/gems/erubi@1.13.0.rbi +150 -0
  231. data/sorbet/rbi/gems/json@2.7.2.rbi +1562 -0
  232. data/sorbet/rbi/gems/language_server-protocol@3.17.0.3.rbi +14238 -0
  233. data/sorbet/rbi/gems/lint_roller@1.1.0.rbi +240 -0
  234. data/sorbet/rbi/gems/method_source@1.1.0.rbi +304 -0
  235. data/sorbet/rbi/gems/netrc@0.11.0.rbi +159 -0
  236. data/sorbet/rbi/gems/nokogiri@1.16.7.rbi +7311 -0
  237. data/sorbet/rbi/gems/parallel@1.26.3.rbi +291 -0
  238. data/sorbet/rbi/gems/parser@3.3.5.0.rbi +5519 -0
  239. data/sorbet/rbi/gems/prism@1.2.0.rbi +39085 -0
  240. data/sorbet/rbi/gems/pry-byebug@3.10.1.rbi +1151 -0
  241. data/sorbet/rbi/gems/pry@0.14.2.rbi +10076 -0
  242. data/sorbet/rbi/gems/racc@1.8.1.rbi +162 -0
  243. data/sorbet/rbi/gems/rainbow@3.1.1.rbi +403 -0
  244. data/sorbet/rbi/gems/rake@13.2.1.rbi +3074 -0
  245. data/sorbet/rbi/gems/rbi@0.2.1.rbi +4535 -0
  246. data/sorbet/rbi/gems/rbtree3@0.7.1.rbi +9 -0
  247. data/sorbet/rbi/gems/regexp_parser@2.9.2.rbi +3772 -0
  248. data/sorbet/rbi/gems/rexml@3.3.8.rbi +4858 -0
  249. data/sorbet/rbi/gems/rspec-core@3.13.1.rbi +11132 -0
  250. data/sorbet/rbi/gems/rspec-expectations@3.13.3.rbi +8183 -0
  251. data/sorbet/rbi/gems/rspec-mocks@3.13.1.rbi +5341 -0
  252. data/sorbet/rbi/gems/rspec-support@3.13.1.rbi +1630 -0
  253. data/sorbet/rbi/gems/rspec@3.13.0.rbi +83 -0
  254. data/sorbet/rbi/gems/rubocop-ast@1.32.3.rbi +7054 -0
  255. data/sorbet/rbi/gems/rubocop-performance@1.21.1.rbi +9 -0
  256. data/sorbet/rbi/gems/rubocop@1.65.1.rbi +58182 -0
  257. data/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +1318 -0
  258. data/sorbet/rbi/gems/simplecov-html@0.13.1.rbi +225 -0
  259. data/sorbet/rbi/gems/simplecov@0.22.0.rbi +2149 -0
  260. data/sorbet/rbi/gems/simplecov_json_formatter@0.1.4.rbi +9 -0
  261. data/sorbet/rbi/gems/spoom@1.5.0.rbi +4932 -0
  262. data/sorbet/rbi/gems/standard-custom@1.0.2.rbi +9 -0
  263. data/sorbet/rbi/gems/standard-performance@1.4.0.rbi +9 -0
  264. data/sorbet/rbi/gems/standard@1.40.0.rbi +926 -0
  265. data/sorbet/rbi/gems/tapioca@0.16.3.rbi +3596 -0
  266. data/sorbet/rbi/gems/tdigest@0.2.1.rbi +170 -0
  267. data/sorbet/rbi/gems/thor@1.3.2.rbi +4378 -0
  268. data/sorbet/rbi/gems/unicode-display_width@2.6.0.rbi +66 -0
  269. data/sorbet/rbi/gems/yard-sorbet@0.9.0.rbi +435 -0
  270. data/sorbet/rbi/gems/yard@0.9.37.rbi +18379 -0
  271. data/sorbet/rbi/todo.rbi +31 -0
  272. data/sorbet/tapioca/config.yml +13 -0
  273. data/sorbet/tapioca/require.rb +15 -0
  274. data/tasks/dsl.rake +22 -0
  275. 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