├── .envrc ├── .gitattributes ├── .github ├── collect-release-artifacts.sh ├── fix-docs-version.sh ├── maven-central-deploy.sh ├── next-minor-snapshot.sh ├── semver-check.sh ├── settings.xml ├── update-sample-version.sh ├── vuepress-deploy.sh └── workflows │ ├── build.yml │ └── release.yml ├── .gitignore ├── .idea └── icon.png ├── .mvn └── maven.config ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── checkstyle.xml ├── devbox.json ├── devbox.lock ├── docs ├── .gitignore ├── .vuepress │ ├── client.ts │ ├── components │ │ ├── AutoLink.vue │ │ ├── Carousel.vue │ │ ├── HomeFeatures.vue │ │ ├── HomeHero.vue │ │ ├── NavbarBrand.vue │ │ └── Testimonial.vue │ ├── config.ts │ ├── plugins │ │ ├── includedRelativeLinkSolverPlugin.ts │ │ └── repoLinkSolverPlugin.ts │ ├── public │ │ ├── favicon.ico │ │ └── logo.svg │ └── styles │ │ └── index.scss ├── diagrams │ ├── codegeneration.puml │ ├── core.puml │ ├── http.puml │ ├── simplified.puml │ └── style.puml ├── guide │ ├── autostop.md │ ├── debugging │ │ ├── debug-groovy.md │ │ ├── debug-jmeter.md │ │ ├── debug-post-processor.md │ │ ├── dummy-sampler.md │ │ ├── images │ │ │ ├── jmeter-http-sampler-debugging.png │ │ │ ├── post-processor-debugging.png │ │ │ ├── test-plan-gui.png │ │ │ └── view-results-tree.png │ │ ├── index.md │ │ ├── post-processor-debugging.md │ │ ├── show-in-gui.md │ │ └── view-results-tree.md │ ├── index.md │ ├── jmx.md │ ├── jmx2dsl.md │ ├── protocols │ │ ├── graphql.md │ │ ├── http │ │ │ ├── auth.md │ │ │ ├── connections.md │ │ │ ├── cookies-and-cache.md │ │ │ ├── defaults.md │ │ │ ├── embedded-resources.md │ │ │ ├── headers.md │ │ │ ├── index.md │ │ │ ├── keepAlive.md │ │ │ ├── methods-and-body.md │ │ │ ├── multipart.md │ │ │ ├── override-defaults.md │ │ │ ├── parameters.md │ │ │ ├── proxy.md │ │ │ ├── redirects.md │ │ │ └── timeouts.md │ │ ├── index.md │ │ ├── java.md │ │ ├── jdbc.md │ │ ├── selenium.md │ │ └── websocket.md │ ├── recorder │ │ ├── config-ide-autocomplete.png │ │ ├── index.md │ │ └── jmdsl-recorder.gif │ ├── reporting │ │ ├── dashboard.md │ │ ├── dashboard.png │ │ ├── html-reporter.md │ │ ├── index.md │ │ ├── logging.md │ │ └── real-time │ │ │ ├── datadog.md │ │ │ ├── datadog.png │ │ │ ├── elasticsearch.md │ │ │ ├── elasticsearch │ │ │ ├── docker-compose.yml │ │ │ ├── elasticsearch-bootstrap │ │ │ │ ├── Dockerfile │ │ │ │ └── index-template.json │ │ │ └── grafana-provisioning │ │ │ │ ├── dashboards │ │ │ │ ├── dashboard.yml │ │ │ │ └── jmeter.json │ │ │ │ └── datasources │ │ │ │ └── datasource.yml │ │ │ ├── graphite.md │ │ │ ├── graphite │ │ │ ├── docker-compose.yml │ │ │ ├── grafana-provisioning │ │ │ │ ├── dashboards │ │ │ │ │ ├── dashboard.yml │ │ │ │ │ └── jmeter.json │ │ │ │ └── datasources │ │ │ │ │ └── datasource.yml │ │ │ └── graphite-conf │ │ │ │ ├── carbon.conf │ │ │ │ └── storage-schemas.conf │ │ │ ├── index.md │ │ │ ├── influxdb.md │ │ │ ├── influxdb │ │ │ ├── docker-compose.yml │ │ │ ├── grafana-provisioning │ │ │ │ ├── dashboards │ │ │ │ │ ├── dashboard.yml │ │ │ │ │ └── jmeter.json │ │ │ │ └── datasources │ │ │ │ │ └── datasource.yml │ │ │ └── grafana.png │ │ │ ├── prometheus.md │ │ │ └── prometheus │ │ │ ├── docker-compose.yml │ │ │ ├── grafana-provisioning │ │ │ ├── dashboards │ │ │ │ ├── dashboard.yml │ │ │ │ └── jmeter.json │ │ │ └── datasources │ │ │ │ └── datasource.yml │ │ │ └── prometheus.yml │ ├── request-generation │ │ ├── counter.md │ │ ├── csv-dataset.md │ │ ├── group-requests.md │ │ ├── if-controller.md │ │ ├── index.md │ │ ├── jsr223-pre-processor.md │ │ ├── loops │ │ │ ├── foreach-controller.md │ │ │ ├── forloop-controller.md │ │ │ ├── index.md │ │ │ ├── once-only-controller.md │ │ │ ├── runtime-controller.md │ │ │ └── while-controller.md │ │ ├── parallel-controller.md │ │ ├── percent-controller.md │ │ ├── timers │ │ │ ├── constant-and-random.md │ │ │ ├── index.md │ │ │ ├── not-synchronized-samples.png │ │ │ ├── synchronized-samples.png │ │ │ ├── synchronizing-timer.md │ │ │ └── throughput-timer.md │ │ └── weighted-switch-controller.md │ ├── response-processing │ │ ├── correlation │ │ │ ├── boundary-extractor.md │ │ │ ├── index.md │ │ │ ├── json-extractor.md │ │ │ └── regex-extractor.md │ │ ├── index.md │ │ ├── json-assertion.md │ │ ├── jsr223-post-processor.md │ │ ├── lambdas.md │ │ └── response-assertion.md │ ├── scale │ │ ├── azure.md │ │ ├── azure.png │ │ ├── blazemeter.md │ │ ├── blazemeter.png │ │ ├── distributed │ │ │ ├── docker-compose.yml │ │ │ ├── jmeter │ │ │ │ └── Dockerfile │ │ │ ├── rmi_keystore.jks │ │ │ └── test │ │ │ │ ├── pom.xml │ │ │ │ ├── rmi_keystore.jks │ │ │ │ └── src │ │ │ │ └── test │ │ │ │ └── java │ │ │ │ └── PerformanceTest.java │ │ ├── index.md │ │ ├── jmeter-remote-testing.md │ │ ├── octoperf.md │ │ └── octoperf.png │ ├── setup.md │ ├── simple-test-plan.md │ ├── test-resources.md │ ├── thread-groups │ │ ├── images │ │ │ ├── rps-thread-group-timeline.png │ │ │ ├── ultimate-thread-group-gui.png │ │ │ └── ultimate-thread-group-timeline.png │ │ ├── index.md │ │ ├── order.md │ │ ├── ramps-and-holds.md │ │ ├── rps-thread-group.md │ │ └── setup-and-teardown.md │ ├── variables-and-properties │ │ ├── index.md │ │ ├── properties.md │ │ └── variables.md │ └── wrapper.md ├── index.md ├── motivation │ ├── index.md │ └── sample.jmx ├── package.json ├── pnpm-lock.yaml ├── support │ ├── abstracta-logo.png │ ├── azure-logo.png │ ├── blazemeter-logo.png │ ├── index.md │ └── octoperf-logo.png └── testimonials.md ├── jmeter-java-dsl-azure ├── pom.xml └── src │ ├── main │ ├── java │ │ └── us │ │ │ └── abstracta │ │ │ └── jmeter │ │ │ └── javadsl │ │ │ └── azure │ │ │ ├── AzureClient.java │ │ │ ├── AzureEngine.java │ │ │ ├── AzureTestPlanStats.java │ │ │ ├── AzureTestStopper.java │ │ │ └── api │ │ │ ├── AppComponents.java │ │ │ ├── AzureResource.java │ │ │ ├── FileInfo.java │ │ │ ├── LoadTest.java │ │ │ ├── LoadTestResource.java │ │ │ ├── Location.java │ │ │ ├── ResourceGroup.java │ │ │ ├── ResponseList.java │ │ │ ├── Secret.java │ │ │ ├── Subscription.java │ │ │ ├── TestRun.java │ │ │ ├── Token.java │ │ │ └── TransactionStats.java │ └── resources │ │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── version.txt │ └── test │ ├── java │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── azure │ │ └── AzureEngineIT.java │ └── resources │ ├── log4j2.xml │ └── users.csv ├── jmeter-java-dsl-base-remote-engine ├── pom.xml └── src │ └── main │ └── java │ └── us │ └── abstracta │ └── jmeter │ └── javadsl │ └── engines │ ├── BaseRemoteEngine.java │ ├── BaseRemoteEngineApiClient.java │ ├── BaseRemoteEngineStatsSummary.java │ ├── RemoteEngineException.java │ └── RemoteEngineTimeMetricSummary.java ├── jmeter-java-dsl-blazemeter ├── pom.xml └── src │ ├── main │ └── java │ │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── blazemeter │ │ ├── BlazeMeterClient.java │ │ ├── BlazeMeterEngine.java │ │ ├── BlazeMeterException.java │ │ ├── BlazeMeterLocation.java │ │ ├── BlazeMeterTestPlanStats.java │ │ └── api │ │ ├── ApiResponse.java │ │ ├── Location.java │ │ ├── Project.java │ │ ├── Test.java │ │ ├── TestConfig.java │ │ ├── TestFile.java │ │ ├── TestFileDeleteRequest.java │ │ ├── TestRun.java │ │ ├── TestRunConfig.java │ │ ├── TestRunRequestStats.java │ │ ├── TestRunStatus.java │ │ ├── TestRunSummaryStats.java │ │ ├── User.java │ │ └── Workspace.java │ └── test │ ├── java │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── blazemeter │ │ └── BlazeMeterEngineTest.java │ └── resources │ ├── log4j2.xml │ └── users.csv ├── jmeter-java-dsl-bridge ├── pom.xml └── src │ ├── main │ └── java │ │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── bridge │ │ ├── BridgeService.java │ │ ├── TestPlanExecution.java │ │ └── serialization │ │ ├── BridgedObjectConstructor.java │ │ ├── BridgedObjectDeserializer.java │ │ ├── BuilderMethod.java │ │ ├── TestElementConstructorException.java │ │ ├── TestPlanStatsSerializer.java │ │ └── constructs │ │ ├── BaseBridgedObjectConstruct.java │ │ ├── BridgedObjectConstruct.java │ │ ├── EngineConstruct.java │ │ ├── HttpHeadersConstruct.java │ │ └── TestPlanExecutionConstruct.java │ └── test │ ├── java │ └── BridgeServiceIT.java │ └── resources │ ├── simpleTestPlan-out.template.yml │ └── simpleTestPlan.yml ├── jmeter-java-dsl-cli ├── pom.xml └── src │ ├── main │ ├── java │ │ └── us │ │ │ └── abstracta │ │ │ └── jmeter │ │ │ └── javadsl │ │ │ └── cli │ │ │ ├── Cli.java │ │ │ ├── JmdslConfig.java │ │ │ ├── Jmx2DslCommand.java │ │ │ └── RecorderCommand.java │ ├── json │ │ └── jmdsl-config-schema.json │ └── resources │ │ └── log4j2.xml │ └── test │ ├── java │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── jmx2dsl │ │ └── Jmx2DslIT.java │ └── resources │ ├── TestPlan.java │ ├── log4j2.xml │ └── test-plan.jmx ├── jmeter-java-dsl-dashboard ├── pom.xml └── src │ ├── main │ └── java │ │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── dashboard │ │ └── DashboardVisualizer.java │ └── test │ ├── java │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── dashboard │ │ └── DashboardVisualizerTest.java │ └── resources │ └── log4j2.xml ├── jmeter-java-dsl-datadog ├── pom.xml └── src │ ├── main │ └── java │ │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── datadog │ │ └── DatadogBackendListener.java │ └── test │ ├── java │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── datadog │ │ ├── DatadogApiClient.java │ │ └── DatadogBackendListenerTest.java │ └── resources │ └── log4j2.xml ├── jmeter-java-dsl-elasticsearch-listener ├── pom.xml └── src │ ├── main │ └── java │ │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── elasticsearch │ │ └── listener │ │ └── ElasticsearchBackendListener.java │ └── test │ ├── java │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── elasticsearch │ │ └── listener │ │ └── ElasticsearchBackendListenerTest.java │ └── resources │ ├── index-template.json │ └── log4j2.xml ├── jmeter-java-dsl-graphql ├── pom.xml └── src │ ├── main │ └── java │ │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── graphql │ │ └── DslGraphqlSampler.java │ └── test │ └── java │ └── us │ └── abstracta │ └── jmeter │ └── javadsl │ └── graphql │ └── DslGraphqlSamplerTest.java ├── jmeter-java-dsl-jdbc ├── pom.xml └── src │ ├── main │ └── java │ │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── jdbc │ │ ├── DslJdbcConnectionPool.java │ │ ├── DslJdbcSampler.java │ │ └── JdbcJmeterDsl.java │ └── test │ ├── java │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── jdbc │ │ ├── DslJdbcConnectionPoolTest.java │ │ ├── DslJdbcSamplerTest.java │ │ └── JdbcJmeterDslTest.java │ └── resources │ └── init.sql ├── jmeter-java-dsl-octoperf ├── pom.xml └── src │ ├── main │ └── java │ │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── octoperf │ │ ├── OctoPerfClient.java │ │ ├── OctoPerfEngine.java │ │ ├── OctoPerfException.java │ │ ├── OctoPerfTestPlanStats.java │ │ └── api │ │ ├── BenchReport.java │ │ ├── BenchResult.java │ │ ├── Project.java │ │ ├── Provider.java │ │ ├── Scenario.java │ │ ├── TableEntry.java │ │ ├── User.java │ │ ├── UserProfile.java │ │ ├── VirtualUser.java │ │ └── Workspace.java │ └── test │ ├── java │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── octoperf │ │ └── OctoPerfEngineTest.java │ └── resources │ └── log4j2.xml ├── jmeter-java-dsl-parallel ├── parallel.jmx ├── pom.xml └── src │ ├── main │ └── java │ │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── parallel │ │ └── ParallelController.java │ └── test │ ├── java │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── parallel │ │ └── ParallelControllerTest.java │ └── resources │ └── log4j2.xml ├── jmeter-java-dsl-prometheus ├── pom.xml └── src │ ├── main │ └── java │ │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── prometheus │ │ └── DslPrometheusListener.java │ └── test │ └── java │ └── us │ └── abstracta │ └── jmeter │ └── javadsl │ └── prometheus │ └── DslPrometheusListenerTest.java ├── jmeter-java-dsl-recorder ├── pom.xml └── src │ ├── main │ ├── java │ │ └── us │ │ │ └── abstracta │ │ │ └── jmeter │ │ │ └── javadsl │ │ │ └── recorder │ │ │ ├── JmeterDslRecorder.java │ │ │ ├── JmeterProxyRecorder.java │ │ │ ├── RecordingBrowser.java │ │ │ └── correlations │ │ │ ├── CorrelationExtractorBuilder.java │ │ │ ├── CorrelationReplacementBuilder.java │ │ │ └── CorrelationRuleBuilder.java │ └── resources │ │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── version.txt │ └── test │ ├── java │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── recorder │ │ ├── JmeterDslRecorderIT.java │ │ ├── RetailStoreHomePage.java │ │ └── RetailStoreMock.java │ └── resources │ ├── RecordedTestPlan.template.java │ ├── log4j2.xml │ └── retailstore-mock │ ├── __files │ ├── assets │ │ ├── chrono_classic.jpg │ │ ├── css │ │ │ └── styles.css │ │ ├── gentleman.jpg │ │ ├── pocket_watch.jpg │ │ └── wood_watch.jpg │ ├── cart.html │ ├── home.html │ └── webjars │ │ ├── bootstrap-icons │ │ └── font │ │ │ ├── bootstrap-icons.css │ │ │ └── fonts │ │ │ └── bootstrap-icons.woff2 │ │ └── bootstrap │ │ └── dist │ │ ├── css │ │ └── bootstrap.min.css │ │ └── js │ │ └── bootstrap.min.js │ └── mappings │ └── mappings.json ├── jmeter-java-dsl-websocket ├── pom.xml └── src │ ├── main │ └── java │ │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── websocket │ │ └── WebsocketJMeterDsl.java │ └── test │ ├── java │ ├── DslWebsocketSamplerTest.java │ ├── WebSocketEchoServer.java │ └── WebsocketCodeGeneratorTest.java │ └── resources │ └── websocket-codegeneration │ ├── ComplexWebSocketTest.java │ ├── SimpleWebSocketTest.java │ ├── WebSocketWithVariablesTest.java │ ├── complex-websocket.jmx │ ├── websocket-test-plan.template.jmx │ └── websocket-with-variables.jmx ├── jmeter-java-dsl-wrapper ├── pom.xml └── src │ ├── main │ └── java │ │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── wrapper │ │ ├── WrapperJmeterDsl.java │ │ └── wrappers │ │ ├── DslControllerWrapper.java │ │ ├── DslSamplerWrapper.java │ │ ├── DslThreadGroupWrapper.java │ │ ├── MultiLevelTestElementWrapper.java │ │ ├── TestElementWrapper.java │ │ ├── TestElementWrapperCallBuilder.java │ │ └── TestElementWrapperHelper.java │ └── test │ ├── java │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── wrapper │ │ ├── WrapperJmeterDslTest.java │ │ └── customelements │ │ ├── MyAssertion.java │ │ ├── MyAssertionGui.java │ │ ├── MyAssertionTestBean.java │ │ ├── MyController.java │ │ ├── MyControllerGui.java │ │ ├── MyControllerTestBean.java │ │ ├── MySampler.java │ │ ├── MySamplerGui.java │ │ ├── MySamplerTestBean.java │ │ ├── MyThreadGroup.java │ │ ├── MyThreadGroupGui.java │ │ └── MyThreadGroupTestBean.java │ └── resources │ └── log4j2.xml ├── jmeter-java-dsl ├── pom.xml └── src │ ├── main │ ├── java │ │ └── us │ │ │ └── abstracta │ │ │ └── jmeter │ │ │ └── javadsl │ │ │ ├── JmeterDsl.java │ │ │ ├── codegeneration │ │ │ ├── CodeSegment.java │ │ │ ├── Comment.java │ │ │ ├── DslCodeGenerator.java │ │ │ ├── Indentation.java │ │ │ ├── MethodCall.java │ │ │ ├── MethodCallBuilder.java │ │ │ ├── MethodCallBuilderRegistry.java │ │ │ ├── MethodCallContext.java │ │ │ ├── MethodParam.java │ │ │ ├── SingleGuiClassCallBuilder.java │ │ │ ├── SingleTestElementCallBuilder.java │ │ │ ├── TestClassTemplate.java │ │ │ ├── TestElementParamBuilder.java │ │ │ └── params │ │ │ │ ├── BoolParam.java │ │ │ │ ├── ChildrenParam.java │ │ │ │ ├── DoubleParam.java │ │ │ │ ├── DurationParam.java │ │ │ │ ├── DynamicParam.java │ │ │ │ ├── EncodingParam.java │ │ │ │ ├── EnumParam.java │ │ │ │ ├── FixedParam.java │ │ │ │ ├── FloatParam.java │ │ │ │ ├── IntParam.java │ │ │ │ ├── LongParam.java │ │ │ │ ├── NameParam.java │ │ │ │ ├── StringArrayParam.java │ │ │ │ └── StringParam.java │ │ │ ├── core │ │ │ ├── BuildTreeContext.java │ │ │ ├── DslJmeterEngine.java │ │ │ ├── DslTestElement.java │ │ │ ├── DslTestPlan.java │ │ │ ├── TestPlanStats.java │ │ │ ├── assertions │ │ │ │ ├── DslAssertion.java │ │ │ │ ├── DslJsonAssertion.java │ │ │ │ └── DslResponseAssertion.java │ │ │ ├── configs │ │ │ │ ├── BaseConfigElement.java │ │ │ │ ├── DslConfig.java │ │ │ │ ├── DslCounter.java │ │ │ │ ├── DslCsvDataSet.java │ │ │ │ └── DslVariables.java │ │ │ ├── controllers │ │ │ │ ├── BaseController.java │ │ │ │ ├── DslController.java │ │ │ │ ├── DslForEachController.java │ │ │ │ ├── DslIfController.java │ │ │ │ ├── DslIncludeController.java │ │ │ │ ├── DslModuleController.java │ │ │ │ ├── DslOnceOnlyController.java │ │ │ │ ├── DslProxyControl.java │ │ │ │ ├── DslRecordingController.java │ │ │ │ ├── DslRuntimeController.java │ │ │ │ ├── DslSimpleController.java │ │ │ │ ├── DslTestFragmentController.java │ │ │ │ ├── DslTransactionController.java │ │ │ │ ├── DslWeightedSwitchController.java │ │ │ │ ├── DslWhileController.java │ │ │ │ ├── ForLoopController.java │ │ │ │ ├── FragmentMethodCall.java │ │ │ │ └── PercentController.java │ │ │ ├── engines │ │ │ │ ├── AutoStoppedTestException.java │ │ │ │ ├── BaseTestStopper.java │ │ │ │ ├── DistributedJmeterEngine.java │ │ │ │ ├── EmbeddedJmeterEngine.java │ │ │ │ ├── EmbeddedStatsSummary.java │ │ │ │ ├── JmeterEnvironment.java │ │ │ │ ├── JmeterGui.java │ │ │ │ └── TestStopper.java │ │ │ ├── listeners │ │ │ │ ├── AutoStopListener.java │ │ │ │ ├── BaseListener.java │ │ │ │ ├── DslBackendListener.java │ │ │ │ ├── DslListener.java │ │ │ │ ├── DslViewResultsTree.java │ │ │ │ ├── DslVisualizer.java │ │ │ │ ├── GraphiteBackendListener.java │ │ │ │ ├── HtmlReporter.java │ │ │ │ ├── InfluxDbBackendListener.java │ │ │ │ ├── JtlWriter.java │ │ │ │ ├── ResponseFileSaver.java │ │ │ │ └── autostop │ │ │ │ │ ├── AutoStopAggregation.java │ │ │ │ │ ├── AutoStopComparison.java │ │ │ │ │ ├── AutoStopConditionElement.java │ │ │ │ │ ├── AutoStopMetric.java │ │ │ │ │ ├── AutoStopTestBean.java │ │ │ │ │ ├── AutoStopTestBeanBeanInfo.java │ │ │ │ │ └── aggregators │ │ │ │ │ ├── AutoStopAggregator.java │ │ │ │ │ ├── AverageAggregator.java │ │ │ │ │ ├── PerSecondAggregator.java │ │ │ │ │ ├── PercentAggregator.java │ │ │ │ │ ├── PercentileAggregator.java │ │ │ │ │ └── SimpleAggregator.java │ │ │ ├── postprocessors │ │ │ │ ├── DslBoundaryExtractor.java │ │ │ │ ├── DslDebugPostProcessor.java │ │ │ │ ├── DslJsonExtractor.java │ │ │ │ ├── DslJsr223PostProcessor.java │ │ │ │ ├── DslPostProcessor.java │ │ │ │ ├── DslRegexExtractor.java │ │ │ │ └── DslVariableExtractor.java │ │ │ ├── preprocessors │ │ │ │ ├── DslJsr223PreProcessor.java │ │ │ │ └── DslPreProcessor.java │ │ │ ├── samplers │ │ │ │ ├── BaseSampler.java │ │ │ │ ├── DslDummySampler.java │ │ │ │ ├── DslFlowControlAction.java │ │ │ │ └── DslSampler.java │ │ │ ├── stats │ │ │ │ ├── CountMetricSummary.java │ │ │ │ ├── StatsSummary.java │ │ │ │ └── TimeMetricSummary.java │ │ │ ├── testelements │ │ │ │ ├── BaseTestElement.java │ │ │ │ ├── DslJsr223TestElement.java │ │ │ │ ├── DslScopedTestElement.java │ │ │ │ ├── MultiLevelTestElement.java │ │ │ │ └── TestElementContainer.java │ │ │ ├── threadgroups │ │ │ │ ├── BaseThreadGroup.java │ │ │ │ ├── DslDefaultThreadGroup.java │ │ │ │ ├── DslSetupThreadGroup.java │ │ │ │ ├── DslSimpleThreadGroup.java │ │ │ │ ├── DslTeardownThreadGroup.java │ │ │ │ ├── DslThreadGroup.java │ │ │ │ ├── LoadTimeLine.java │ │ │ │ ├── RpsThreadGroup.java │ │ │ │ └── defaultthreadgroup │ │ │ │ │ ├── SimpleThreadGroupHelper.java │ │ │ │ │ ├── Stage.java │ │ │ │ │ └── UltimateThreadGroupHelper.java │ │ │ ├── timers │ │ │ │ ├── BaseTimer.java │ │ │ │ ├── DslConstantTimer.java │ │ │ │ ├── DslSynchronizingTimer.java │ │ │ │ ├── DslThroughputTimer.java │ │ │ │ ├── DslTimer.java │ │ │ │ └── DslUniformRandomTimer.java │ │ │ └── util │ │ │ │ ├── DslScript.java │ │ │ │ ├── JmeterFunction.java │ │ │ │ ├── PropertyScriptBuilder.java │ │ │ │ ├── SingleSeriesTimelinePanel.java │ │ │ │ └── StringTemplate.java │ │ │ ├── http │ │ │ ├── AutoEnabledHttpConfigElement.java │ │ │ ├── ContentTypeParam.java │ │ │ ├── DslAuthManager.java │ │ │ ├── DslBaseHttpSampler.java │ │ │ ├── DslCacheManager.java │ │ │ ├── DslCookieManager.java │ │ │ ├── DslHttpDefaults.java │ │ │ ├── DslHttpSampler.java │ │ │ ├── HttpElementHelper.java │ │ │ ├── HttpHeaders.java │ │ │ └── JmeterUrl.java │ │ │ ├── java │ │ │ └── DslJsr223Sampler.java │ │ │ └── util │ │ │ └── TestResource.java │ └── resources │ │ ├── TestClass.template.java │ │ ├── default-dependencies.txt │ │ ├── default-imports.txt │ │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ └── core │ │ └── listeners │ │ └── autostop │ │ └── AutoStopTestBeanResources.properties │ └── test │ ├── java │ ├── com │ │ └── github │ │ │ └── caciocavallosilano │ │ │ └── cacio │ │ │ └── ctc │ │ │ └── CTCGraphicsConfiguration.java │ ├── org │ │ └── apache │ │ │ └── jmeter │ │ │ └── gui │ │ │ └── util │ │ │ └── MenuFactory.java │ └── us │ │ └── abstracta │ │ └── jmeter │ │ └── javadsl │ │ ├── JmeterDslTest.java │ │ ├── TestExecutionLogger.java │ │ ├── codegeneration │ │ ├── DslCodeGeneratorTest.java │ │ └── MethodCallBuilderTest.java │ │ ├── core │ │ ├── DslTestPlanTest.java │ │ ├── JmeterDslCoreTest.java │ │ ├── StringTemplateAssert.java │ │ ├── assertions │ │ │ ├── DslJsonAssertionTest.java │ │ │ └── DslResponseAssertionTest.java │ │ ├── configs │ │ │ ├── CsvDataSetTest.java │ │ │ ├── DslCounterTest.java │ │ │ └── DslVariablesTest.java │ │ ├── controllers │ │ │ ├── DslForEachControllerTest.java │ │ │ ├── DslIfControllerTest.java │ │ │ ├── DslIncludeControllerTest.java │ │ │ ├── DslModuleControllerTest.java │ │ │ ├── DslOnceOnlyControllerTest.java │ │ │ ├── DslRuntimeControllerTest.java │ │ │ ├── DslSimpleControllerTest.java │ │ │ ├── DslTestFragmentControllerTest.java │ │ │ ├── DslTransactionControllerTest.java │ │ │ ├── DslWeightedSwitchControllerTest.java │ │ │ ├── DslWhileControllerTest.java │ │ │ ├── ForLoopControllerTest.java │ │ │ ├── MethodCallFragmentBuilderTest.java │ │ │ └── PercentControllerTest.java │ │ ├── engines │ │ │ ├── DistributedJmeterEngineTest.java │ │ │ └── EmbeddedJmeterEngineTest.java │ │ ├── listeners │ │ │ ├── AutoStopListenerIT.java │ │ │ ├── AutoStopTestBeanTest.java │ │ │ ├── DslViewResultsTreeTest.java │ │ │ ├── DslVisualizerTest.java │ │ │ ├── GraphiteBackendListenerTest.java │ │ │ ├── HtmlReporterTest.java │ │ │ ├── InfluxDbBackendListenerTest.java │ │ │ ├── JtlWriterTest.java │ │ │ └── ResponseFileSaverTest.java │ │ ├── postprocessors │ │ │ ├── DslBoundaryExtractorTest.java │ │ │ ├── DslDebugPostProcessorTest.java │ │ │ ├── DslJsonExtractorTest.java │ │ │ ├── DslJsr223PostProcessorTest.java │ │ │ └── DslRegexExtractorTest.java │ │ ├── preprocessors │ │ │ └── DslJsr223PreProcessorTest.java │ │ ├── samplers │ │ │ ├── DslDummySamplerTest.java │ │ │ └── DslFlowControlActionTest.java │ │ ├── threadgroups │ │ │ ├── DslDefaultThreadGroupTest.java │ │ │ ├── DslSetupThreadGroupTest.java │ │ │ ├── DslTeardownThreadGroupTest.java │ │ │ └── RpsThreadGroupTest.java │ │ └── timers │ │ │ ├── DslConstantTimerTest.java │ │ │ ├── DslSynchronizingTimerTest.java │ │ │ ├── DslThroughputTimerTest.java │ │ │ └── DslUniformRandomTimerTest.java │ │ ├── http │ │ ├── DslAuthManagerTest.java │ │ ├── DslCacheManagerTest.java │ │ ├── DslCookieManagerTest.java │ │ ├── DslHttpDefaultsTest.java │ │ ├── DslHttpSamplerTest.java │ │ ├── HttpHeadersTest.java │ │ ├── HttpResponseBuilder.java │ │ ├── JmeterUrlTest.java │ │ └── ProxyServer.java │ │ └── java │ │ └── DslJsr223SamplerTest.java │ └── resources │ ├── META-INF │ └── services │ │ └── org.junit.platform.launcher.TestExecutionListener │ ├── codegeneration │ ├── DisabledElements.java │ ├── RecordedTest.java │ ├── SimpleTest.java │ ├── disabled-elements.jmx │ ├── fragments │ │ ├── HttpSamplerDsl.java │ │ ├── IfControllerDsl.java │ │ ├── TestFragmentMethodDsl.template.java │ │ ├── fragment.template.jmx │ │ ├── http-sampler.jmx │ │ ├── if-controller.jmx │ │ ├── include-controller.template.jmx │ │ ├── module.jmx │ │ └── thread-group.template.jmx │ ├── recorded.jmx │ └── test-plan.template.jmx │ ├── datasets │ ├── dataset-long.csv │ ├── dataset-with-alt-format.csv │ └── dataset-with-headers.csv │ ├── graphite │ ├── carbon.conf │ └── storage-schemas.conf │ ├── jtls │ ├── complete-jtl.template.xml │ ├── custom-sample-jtl.xml │ ├── default-jtl.template.csv │ └── jtl-with-custom-variable.template.csv │ ├── log4j2.xml │ ├── rmi_keystore.jks │ ├── sample.properties │ └── test-plan.template.jmx └── pom.xml /.envrc: -------------------------------------------------------------------------------- 1 | # Automatically sets up your devbox environment whenever you cd into this 2 | # directory via our direnv integration: 3 | 4 | eval "$(devbox generate direnv --print-envrc)" 5 | 6 | # check out https://www.jetpack.io/devbox/docs/ide_configuration/direnv/ 7 | # for more details 8 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf -------------------------------------------------------------------------------- /.github/collect-release-artifacts.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This script solves artifacts to be uploaded to GH release 4 | set -eo pipefail 5 | 6 | RET=$(find . -iname '*.jar' -and -not -iname '*-sources.jar' -and -not -iname '*-javadoc.jar' -and -not -iname '*-tests.jar' -and -not -iname 'original-*.jar' -and -not -iname '*-jmdsl-*.jar' -or -type d -name dependency -prune -and -not -iname 'dependency' | awk '{printf $0","}') 7 | echo "${RET%?},./jmeter-java-dsl-cli/src/main/json/jmdsl-config-schema.json" 8 | -------------------------------------------------------------------------------- /.github/fix-docs-version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This script takes care of setting proper jmeter-java-dsl version in docs. 4 | # 5 | set -eo pipefail 6 | 7 | VERSION=$1 8 | 9 | update_file_versions() { 10 | local VERSION="$1" 11 | local FILE="$2" 12 | sed -i "s/jmeter-java-dsl\([^ :]*\):[0-9.]\+/jmeter-java-dsl\1:${VERSION}/g" "${FILE}" 13 | sed -i "/jmeter-java-dsl.*<\/artifactId>$/{N;s/jmeter-java-dsl\(.*\)<\/artifactId>\n\( *\).*<\/version>/jmeter-java-dsl\1<\/artifactId>\n\2${VERSION}<\/version>/}" "${FILE}" 14 | } 15 | 16 | update_file_versions ${VERSION} README.md 17 | 18 | find docs -name "*.md" -o -name "*.xml" -not -path "*/node_modules/*" | while read DOC_FILE; do 19 | update_file_versions ${VERSION} ${DOC_FILE} 20 | done -------------------------------------------------------------------------------- /.github/maven-central-deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This script takes care of deploying tagged versions to maven central and updating the pom.xml 4 | # version with next development version. 5 | # 6 | # Required environment variables: GPG_SECRET_KEYS, GPG_OWNERTRUST, GPG_EXECUTABLE 7 | 8 | set -eo pipefail 9 | 10 | echo $GPG_SECRET_KEYS | base64 --decode | $GPG_EXECUTABLE --batch --import 11 | echo $GPG_OWNERTRUST | base64 --decode | $GPG_EXECUTABLE --batch --import-ownertrust 12 | mvn --batch-mode deploy -Prelease -DskipTests --settings .github/settings.xml 13 | -------------------------------------------------------------------------------- /.github/next-minor-snapshot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This script solves next minor version 4 | set -eo pipefail 5 | 6 | VERSION="$1" 7 | MAJOR="${VERSION%%.*}" 8 | VERSION="${VERSION#*.}" 9 | MINOR="${VERSION%%.*}" 10 | echo "${MAJOR}.$((MINOR + 1))-SNAPSHOT" 11 | -------------------------------------------------------------------------------- /.github/semver-check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This script checks that the version number of the release is an expected one, and avoid erroneous releases which don't follow semver 4 | set -eo pipefail 5 | 6 | git fetch --tags --quiet 7 | VERSION="$1" 8 | PREV_VERSION=$(git tag --sort=-creatordate | head -1) 9 | PREV_VERSION=${PREV_VERSION#v} 10 | PREV_MAJOR="${PREV_VERSION%%.*}" 11 | PREV_VERSION="${PREV_VERSION#*.}" 12 | PREV_MINOR="${PREV_VERSION%%.*}" 13 | PREV_PATCH="${PREV_VERSION#*.}" 14 | if [[ "$PREV_VERSION" == "$PREV_PATCH" ]]; then 15 | PREV_PATCH="0" 16 | fi 17 | 18 | [[ "$VERSION" == "$PREV_MAJOR.$PREV_MINOR.$((PREV_PATCH + 1))" || "$VERSION" == "$PREV_MAJOR.$((PREV_MINOR + 1))" || "$VERSION" == "$((PREV_MAJOR + 1)).0" ]] 19 | -------------------------------------------------------------------------------- /.github/settings.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | central 9 | ${env.SONATYPE_USERNAME} 10 | ${env.SONATYPE_PASSWORD} 11 | 12 | 13 | 14 | 15 | 16 | central 17 | 18 | true 19 | 20 | 21 | ${env.GPG_EXECUTABLE} 22 | ${env.GPG_PASSPHRASE} 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /.github/update-sample-version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This script takes care of updating jmeter-java-dsl version in sample project. 4 | # 5 | set -eox pipefail 6 | 7 | VERSION=$1 8 | 9 | USER_EMAIL="$(git log --format='%ae' HEAD^!)" 10 | USER_NAME="$(git log --format='%an' HEAD^!)" 11 | 12 | cd jmeter-java-dsl-sample 13 | sed -i "/jmeter-java-dsl<\/artifactId>$/{N;s/jmeter-java-dsl<\/artifactId>\n .*<\/version>/jmeter-java-dsl<\/artifactId>\n ${VERSION}<\/version>/}" pom.xml 14 | git add . 15 | git config --local user.email "$USER_EMAIL" 16 | git config --local user.name "$USER_NAME" 17 | git commit -m "Updated jmeter-java-dsl version" 18 | git push origin HEAD:master 19 | cd .. 20 | rm -rf jmeter-java-dsl-sample 21 | -------------------------------------------------------------------------------- /.github/vuepress-deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # 3 | # This script takes care of building and deploying the vuepress documentation to github pages. 4 | # 5 | set -e 6 | 7 | cd docs 8 | 9 | pnpm install && pnpm build 10 | 11 | cd .vuepress/dist 12 | 13 | EMAIL="$(git log --format='%ae' HEAD^!)" 14 | USERNAME="$(git log --format='%an' HEAD^!)" 15 | git init 16 | git config --local user.email "$EMAIL" 17 | git config --local user.name "$USERNAME" 18 | git add . 19 | git commit -m '[skip ci] Deploy docs to GitHub pages' 20 | 21 | git push -f https://git:${ACCESS_TOKEN}@github.com/abstracta/jmeter-java-dsl.git master:gh-pages 22 | 23 | cd $GITHUB_WORKSPACE 24 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: run tests 2 | on: 3 | push: 4 | tags-ignore: 5 | - "*" 6 | branches: 7 | - "**" 8 | jobs: 9 | test: 10 | runs-on: ubuntu-22.04 11 | concurrency: blazemeter_test 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: actions/setup-java@v4 15 | with: 16 | distribution: temurin 17 | java-version: 11 18 | cache: maven 19 | - uses: browser-actions/setup-chrome@v1 20 | - name: Run maven tests 21 | run: mvn --batch-mode --no-transfer-progress clean install 22 | env: 23 | BZ_TOKEN: ${{ secrets.BZ_TOKEN }} 24 | OCTOPERF_API_KEY: ${{ secrets.OCTOPERF_API_KEY }} 25 | AZURE_CREDS: ${{ secrets.AZURE_CREDS }} 26 | DATADOG_API_KEY: ${{ secrets.DATADOG_API_KEY }} 27 | DATADOG_APPLICATION_KEY: ${{ secrets.DATADOG_APPLICATION_KEY }} 28 | -------------------------------------------------------------------------------- /.idea/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/.idea/icon.png -------------------------------------------------------------------------------- /.mvn/maven.config: -------------------------------------------------------------------------------- 1 | -Dorg.slf4j.simpleLogger.log.org.apache.maven.plugins.javadoc=ERROR -------------------------------------------------------------------------------- /devbox.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | "maven@latest", 4 | "nodejs@latest", 5 | "nodePackages.pnpm@latest", 6 | "temurin-bin-8@latest" 7 | ], 8 | "shell": { 9 | "init_hook": [ 10 | "echo 'Welcome to devbox!' > /dev/null" 11 | ], 12 | "scripts": { 13 | "docs": [ 14 | "pnpm --dir docs dev" 15 | ], 16 | "install": [ 17 | "mvn clean install" 18 | ], 19 | "setup": [ 20 | "pnpm --dir docs install" 21 | ] 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /devbox.lock: -------------------------------------------------------------------------------- 1 | { 2 | "lockfile_version": "1", 3 | "packages": { 4 | "maven@latest": { 5 | "last_modified": "2023-09-10T10:53:27Z", 6 | "resolved": "github:NixOS/nixpkgs/78058d810644f5ed276804ce7ea9e82d92bee293#maven", 7 | "source": "devbox-search", 8 | "version": "3.9.4" 9 | }, 10 | "nodePackages.pnpm@latest": { 11 | "last_modified": "2023-09-10T10:53:27Z", 12 | "resolved": "github:NixOS/nixpkgs/78058d810644f5ed276804ce7ea9e82d92bee293#nodePackages.pnpm", 13 | "source": "devbox-search", 14 | "version": "8.6.12" 15 | }, 16 | "nodejs@latest": { 17 | "last_modified": "2023-09-10T10:53:27Z", 18 | "plugin_version": "0.0.2", 19 | "resolved": "github:NixOS/nixpkgs/78058d810644f5ed276804ce7ea9e82d92bee293#nodejs_20", 20 | "source": "devbox-search", 21 | "version": "20.6.1" 22 | }, 23 | "temurin-bin-8@latest": { 24 | "last_modified": "2023-09-10T10:53:27Z", 25 | "resolved": "github:NixOS/nixpkgs/78058d810644f5ed276804ce7ea9e82d92bee293#temurin-bin-8", 26 | "source": "devbox-search", 27 | "version": "8.0.372" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .vuepress/.cache/ 3 | .vuepress/.temp/ 4 | .vuepress/dist/ 5 | -------------------------------------------------------------------------------- /docs/.vuepress/client.ts: -------------------------------------------------------------------------------- 1 | import { defineClientConfig } from '@vuepress/client' 2 | import { library } from '@fortawesome/fontawesome-svg-core' 3 | import { faDiscord, faGithub, faTwitter, faLinkedin } from '@fortawesome/free-brands-svg-icons' 4 | import { faGlobe, faBullhorn, faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons' 5 | import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome' 6 | 7 | library.add(faDiscord, faGithub, faTwitter, faLinkedin, faGlobe, faBullhorn, faChevronLeft, faChevronRight) 8 | 9 | export default defineClientConfig({ 10 | enhance({ app }) { 11 | app.component('font-awesome-icon', FontAwesomeIcon) 12 | }, 13 | }) -------------------------------------------------------------------------------- /docs/.vuepress/components/HomeFeatures.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 25 | -------------------------------------------------------------------------------- /docs/.vuepress/plugins/includedRelativeLinkSolverPlugin.ts: -------------------------------------------------------------------------------- 1 | import mditPlugin from 'markdown-it-replace-link' 2 | 3 | export const includedRelativeLinkSolverPlugin = ({}) => ({ 4 | name: 'includedRelativeLinkSolverPlugin', 5 | extendsMarkdown: (md) => { 6 | md.use(mditPlugin, { 7 | replaceLink: (link, env) => { 8 | if (link.startsWith('.')) { 9 | let hashPos = link.indexOf('#') 10 | return hashPos > 0 ? link.substring(hashPos) : link 11 | } 12 | return link 13 | } 14 | }) 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /docs/.vuepress/plugins/repoLinkSolverPlugin.ts: -------------------------------------------------------------------------------- 1 | import mditPlugin from 'markdown-it-replace-link' 2 | 3 | export const repoLinkSolverPlugin = ({repoUrl} : {repoUrl: String}) => ({ 4 | name: 'repoLinkSolverPlugin', 5 | extendsMarkdown: (md) => { 6 | md.use(mditPlugin, { 7 | replaceLink: (link, env) => link.startsWith('/') ? repoUrl + '/tree/master' + link : link 8 | }) 9 | } 10 | }); 11 | -------------------------------------------------------------------------------- /docs/.vuepress/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/docs/.vuepress/public/favicon.ico -------------------------------------------------------------------------------- /docs/diagrams/http.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | !include style.puml 3 | 4 | package http { 5 | 6 | abstract class DslBaseHttpSampler { 7 | String url 8 | } 9 | 10 | class DslHttpSampler extends DslBaseHttpSampler { 11 | HttpMethod method 12 | String body 13 | } 14 | 15 | class HttpHeaders { 16 | Map headers 17 | } 18 | 19 | abstract class AutoEnabledHttpConfigElement { 20 | boolean enabled 21 | } 22 | 23 | class DslCacheManager extends AutoEnabledHttpConfigElement 24 | 25 | class DslCookieManager extends AutoEnabledHttpConfigElement 26 | 27 | class DslHttpDefaults 28 | 29 | DslBaseHttpSampler --> HttpHeaders 30 | 31 | } 32 | 33 | package core { 34 | abstract class BaseConfigElement 35 | abstract class BaseSampler 36 | } 37 | 38 | package codegeneration { 39 | } 40 | 41 | DslBaseHttpSampler --|> BaseSampler 42 | HttpHeaders --|> BaseConfigElement 43 | AutoEnabledHttpConfigElement --|> BaseConfigElement 44 | DslHttpDefaults --|> BaseConfigElement 45 | http ..> core 46 | http ..> codegeneration 47 | 48 | @enduml -------------------------------------------------------------------------------- /docs/diagrams/style.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam monochrome true 3 | hide empty members 4 | hide circle 5 | @enduml -------------------------------------------------------------------------------- /docs/guide/debugging/debug-groovy.md: -------------------------------------------------------------------------------- 1 | ### Debug Groovy code 2 | 3 | In some cases, you may want to debug some Groovy script used in some sampler, pre-, or post-processor. For such scenarios, you can check [here](https://github.com/abstracta/jmeter-java-dsl/issues/41#issuecomment-966715062) where we list some options. 4 | -------------------------------------------------------------------------------- /docs/guide/debugging/debug-jmeter.md: -------------------------------------------------------------------------------- 1 | ### Debug JMeter code 2 | 3 | You can even add breakpoints to JMeter code in your IDE and debug the code line by line providing the greatest possible detail. 4 | 5 | Here is an example screenshot debugging HTTP Sampler: 6 | 7 | ![JMeter HTTP Sampler debugging in IDE](./images/jmeter-http-sampler-debugging.png) 8 | 9 | ::: tip 10 | JMeter class in charge of executing threads logic is `org.apache.jmeter.threads.JMeterThread`. You can check the classes used by each DSL-provided test element by checking the DSL code. 11 | ::: 12 | -------------------------------------------------------------------------------- /docs/guide/debugging/images/jmeter-http-sampler-debugging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/docs/guide/debugging/images/jmeter-http-sampler-debugging.png -------------------------------------------------------------------------------- /docs/guide/debugging/images/post-processor-debugging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/docs/guide/debugging/images/post-processor-debugging.png -------------------------------------------------------------------------------- /docs/guide/debugging/images/test-plan-gui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/docs/guide/debugging/images/test-plan-gui.png -------------------------------------------------------------------------------- /docs/guide/debugging/images/view-results-tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/docs/guide/debugging/images/view-results-tree.png -------------------------------------------------------------------------------- /docs/guide/debugging/index.md: -------------------------------------------------------------------------------- 1 | ## Test plan debugging 2 | 3 | A usual requirement while building a test plan is to be able to review requests and responses and debug the test plan for potential issues in the configuration or behavior of the service under test. With jmeter-java-dsl you have several options for this purpose. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /docs/guide/debugging/post-processor-debugging.md: -------------------------------------------------------------------------------- 1 | ### Post-processor breakpoints 2 | 3 | Another alternative is using IDE's built-in debugger by adding a `jsr223PostProcessor` with java code and adding a breakpoint to the post-processor code. This does not only allow checking sample result information but also JMeter variables and properties values and sampler properties. 4 | 5 | Here is an example screenshot using this approach while debugging with an IDE: 6 | 7 | ![Post Processor debugging in IDE](./images/post-processor-debugging.png) 8 | 9 | ::: tip 10 | DSL provides following methods to ease results and variables visualization and debugging: `varsMap()`, `prevMap()`, `prevMetadata()`, `prevMetrics()`, `prevRequest()`, `prevResponse()`. Check [PostProcessorVars](/jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/postprocessors/DslJsr223PostProcessor.java) and [Jsr223ScriptVars](/jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/testelements/DslJsr223TestElement.java) for more details. 11 | ::: 12 | 13 | ::: tip 14 | Remove such post processors when no longer needed (when debugging is finished). Leaving them would generate errors when loading generated JMX test plan or running the test plan in BlazeMeter, OctoPerf or Azure, in addition to unnecessary processing time and resource usage. 15 | ::: 16 | 17 | -------------------------------------------------------------------------------- /docs/guide/debugging/show-in-gui.md: -------------------------------------------------------------------------------- 1 | ### Test plan review in JMeter GUI 2 | 3 | A usual requirement for new DSL users that are used to Jmeter GUI, is to be able to review Jmeter DSL generated test plan in the familiar JMeter GUI. For this, you can use `showInGui()` method in a test plan to open JMeter GUI with the preloaded test plan. 4 | 5 | This can be also used to debug the test plan, by adding elements (like view results tree, dummy samplers, debug post-processors, etc.) in the GUI and running the test plan. 6 | 7 | Here is a simple example using the method: 8 | 9 | ```java 10 | import static us.abstracta.jmeter.javadsl.JmeterDsl.*; 11 | 12 | import java.io.IOException; 13 | import org.junit.jupiter.api.Test; 14 | 15 | public class PerformanceTest { 16 | 17 | @Test 18 | public void testPerformance() throws IOException { 19 | testPlan( 20 | threadGroup(2, 10, 21 | httpSampler("http://my.service") 22 | ) 23 | ).showInGui(); 24 | } 25 | 26 | } 27 | ``` 28 | 29 | Which ends up opening a window like this one: 30 | 31 | ![Test plan in JMeter GUI](./images/test-plan-gui.png) -------------------------------------------------------------------------------- /docs/guide/protocols/http/connections.md: -------------------------------------------------------------------------------- 1 | #### Connections 2 | 3 | jmeter-java-dsl, as JMeter (and also K6), by default **reuses HTTP connections between thread iterations** to avoid common issues with port and file descriptors exhaustion which require manual OS tuning and may manifest in many ways. 4 | 5 | This decision implies that the load generated from 10 threads and 100 iterations is not the same as the one generated by 1000 real users with up to 10 concurrent users in a given time, since the load imposed by each user connection and disconnection would only be generated once for each thread. 6 | 7 | If you need for each iteration to reset connections you can use something like this: 8 | 9 | ```java 10 | httpDefaults() 11 | .resetConnectionsBetweenIterations() 12 | ``` 13 | 14 | If you use this setting you might want to take a look at "Config your environment" section of [this article](https://medium.com/@chientranthien/how-to-generate-high-load-benchmark-with-jmeter-80e828a67592) to avoid port and file descriptors exhaustion. 15 | 16 | ::: tip 17 | Connections are configured by default with a TTL (time-to-live) of 1 minute, which you can easily change like this: 18 | 19 | ```java 20 | httpDefaults() 21 | .connectionTtl(Duration.ofMinutes(10)) 22 | ``` 23 | 24 | * This and `resetConnectionsBetweenIterations` apply at the JVM level (due to JMeter limitation), so they affect all requests in the test plan and other ones potentially running in the same JVM instance. 25 | ::: 26 | 27 | ::: warning 28 | Using `clientImpl(HttpClientImpl.JAVA)` will ignore any of the previous settings and will reuse connections depending on JVM implementation. 29 | ::: 30 | -------------------------------------------------------------------------------- /docs/guide/protocols/http/cookies-and-cache.md: -------------------------------------------------------------------------------- 1 | #### Cookies & caching 2 | 3 | jmeter-java-dsl automatically adds a cookie manager and cache manager for automatic HTTP cookie and caching handling, emulating a browser behavior. If you need to disable them you can use something like this: 4 | 5 | ```java 6 | testPlan( 7 | httpCookies().disable(), 8 | httpCache().disable(), 9 | threadGroup(2, 10, 10 | httpSampler("http://my.service") 11 | ) 12 | ) 13 | ``` 14 | -------------------------------------------------------------------------------- /docs/guide/protocols/http/headers.md: -------------------------------------------------------------------------------- 1 | #### Headers 2 | 3 | You might have already noticed in some of the examples that we have shown already some ways to set some headers. For instance, in the following snippet `Content-Type` header is being set in two different ways: 4 | 5 | ```java 6 | httpSampler("http://my.service") 7 | .post("{\"field\":\"val\"}", Type.APPLICATION_JSON) 8 | httpSampler("http://my.service") 9 | .contentType(Type.APPLICATION_JSON) 10 | ``` 11 | 12 | These are handy methods to specify the `Content-Type` header, but you can also set any header on a particular request using provided `header` method, like this: 13 | 14 | ```java 15 | httpSampler("http://my.service") 16 | .header("X-First-Header", "val1") 17 | .header("X-Second-Header", "val2") 18 | ``` 19 | 20 | Additionally, you can specify headers to be used by all samplers in a test plan, thread group, transaction controllers, etc. For this you can use `httpHeaders` like this: 21 | 22 | ```java 23 | testPlan( 24 | threadGroup(2, 10, 25 | httpHeaders() 26 | .header("X-Header", "val1"), 27 | httpSampler("http://my.service"), 28 | httpSampler("http://my.service/users") 29 | ) 30 | ).run(); 31 | ``` 32 | 33 | ::: tip 34 | You can also use lambda expressions for dynamically building HTTP Headers, but the same limitations apply as in other cases (running in BlazeMeter, OctoPerf, Azure, or using generated JMX file). 35 | ::: 36 | -------------------------------------------------------------------------------- /docs/guide/protocols/http/index.md: -------------------------------------------------------------------------------- 1 | ### HTTP 2 | 3 | Throughout this guide, several examples have been shown for simple cases of HTTP requests (mainly how to do gets and posts), but the DSL provides additional features that you might need to be aware of. 4 | 5 | Here we show some of them, but check [JmeterDsl](/jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/JmeterDsl.java) and [DslHttpSampler](/jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/http/DslHttpSampler.java) to explore all available features. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/guide/protocols/http/methods-and-body.md: -------------------------------------------------------------------------------- 1 | #### Methods & body 2 | 3 | As previously seen, you can do simple gets and posts like in the following snippet: 4 | 5 | ```java 6 | httpSampler("http://my.service") // A simple get 7 | httpSampler("http://my.service") 8 | .post("{\"field\":\"val\"}", Type.APPLICATION_JSON) // simple post 9 | ``` 10 | 11 | But you can also use additional methods to specify any HTTP method and body: 12 | 13 | ```java 14 | httpSampler("http://my.service") 15 | .method(HTTPConstants.PUT) 16 | .contentType(Type.APPLICATION_JSON) 17 | .body("{\"field\":\"val\"}") 18 | ``` 19 | 20 | Additionally, when in need to generate dynamic URLs or bodies, you can use lambda expressions (as previously seen in some examples): 21 | 22 | ```java 23 | httpSampler("http://my.service") 24 | .post(s -> buildRequestBody(s.vars), Type.TEXT_PLAIN) 25 | httpSampler("http://my.service") 26 | .body(s -> buildRequestBody(s.vars)) 27 | httpSampler(s -> buildRequestUrl(s.vars)) // buildRequestUrl is just an example of a custom method you could implement with your own logic 28 | ``` 29 | 30 | ::: warning 31 | As previously mentioned, even though using Java Lambdas has several benefits, they are also less portable. Check [this section](../../response-processing/lambdas.md#lambdas) for more details. 32 | ::: 33 | -------------------------------------------------------------------------------- /docs/guide/protocols/http/multipart.md: -------------------------------------------------------------------------------- 1 | #### Multipart requests 2 | 3 | When you need to upload files to an HTTP server or need to send a complex request body, you will in many cases require sending multipart requests. To send a multipart request just use `bodyPart` and `bodyFilePart` methods like in the following example: 4 | 5 | ```java 6 | import static us.abstracta.jmeter.javadsl.JmeterDsl.*; 7 | 8 | import org.apache.http.entity.ContentType; 9 | import org.apache.jmeter.protocol.http.util.HTTPConstants; 10 | import org.junit.jupiter.api.Test; 11 | 12 | public class PerformanceTest { 13 | 14 | @Test 15 | public void test() throws Exception { 16 | testPlan( 17 | threadGroup(1, 1, 18 | httpSampler("https://myservice.com/report") 19 | .method(HTTPConstants.POST) 20 | .bodyPart("myText", "Hello World", ContentType.TEXT_PLAIN) 21 | .bodyFilePart("myFile", "myReport.xml", ContentType.TEXT_XML) 22 | ) 23 | ).run(); 24 | } 25 | 26 | } 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/guide/protocols/http/parameters.md: -------------------------------------------------------------------------------- 1 | #### Parameters 2 | 3 | In many cases, you will need to specify some URL query string parameters or URL encoded form bodies. For these cases, you can use `param` method as in the following example: 4 | 5 | ```java 6 | import static us.abstracta.jmeter.javadsl.JmeterDsl.*; 7 | 8 | import org.apache.jmeter.protocol.http.util.HTTPConstants; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class PerformanceTest { 12 | 13 | @Test 14 | public void test() throws Exception { 15 | String baseUrl = "https://myservice.com/products"; 16 | testPlan( 17 | threadGroup(1, 1, 18 | // GET https://myservice.com/products?name=iron+chair 19 | httpSampler("GetIronChair", baseUrl) 20 | .param("name", "iron chair"), 21 | /* 22 | * POST https://myservice.com/products 23 | * Content-Type: application/x-www-form-urlencoded 24 | * 25 | * name=wooden+chair 26 | */ 27 | httpSampler("CreateWoodenChair", baseUrl) 28 | .method(HTTPConstants.POST) // POST 29 | .param("name", "wooden chair") 30 | ) 31 | ).run(); 32 | } 33 | 34 | } 35 | ``` 36 | 37 | ::: tip 38 | JMeter automatically URL encodes parameters, so you don't need to worry about special characters in parameter names or values. 39 | 40 | If you want to use some custom encoding or have an already encoded value that you want to use, then you can use `rawParam` method instead which does not apply any encoding to the parameter name or value, and send it as is. 41 | ::: 42 | -------------------------------------------------------------------------------- /docs/guide/protocols/http/proxy.md: -------------------------------------------------------------------------------- 1 | #### Proxy 2 | 3 | Sometimes, due to company policies, some infrastructure requirement or just to further analyze or customize requests, for example, through the usage of tools like [fiddler](https://www.telerik.com/fiddler) and [mitmproxy](https://mitmproxy.org/), you need to specify a proxy server through which HTTP requests are sent to their final destination. This can be easily done with `proxy` method, like in the following example: 4 | 5 | ```java 6 | import static us.abstracta.jmeter.javadsl.JmeterDsl.*; 7 | 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class PerformanceTest { 11 | 12 | @Test 13 | public void test() throws Exception { 14 | testPlan( 15 | threadGroup(1, 1, 16 | httpSampler("https://myservice.com") 17 | .proxy("http://myproxy:8081") 18 | ) 19 | ).run(); 20 | } 21 | 22 | } 23 | ``` 24 | 25 | ::: tip 26 | You can also specify proxy authentication parameters with `proxy(url, username, password)` method. 27 | ::: 28 | 29 | ::: tip 30 | When you need to set a proxy for several samplers, use `httpDefaults().proxy` methods. 31 | ::: 32 | -------------------------------------------------------------------------------- /docs/guide/protocols/http/redirects.md: -------------------------------------------------------------------------------- 1 | #### Redirects 2 | 3 | When jmeter-java-dsl (using JMeter logic) detects a redirection, it will automatically do a request to the redirected URL and register the redirection as a sub-sample of the main request. 4 | 5 | If you want to disable such logic, you can just call `.followRedirects(false)` in a given `httpSampler`. 6 | -------------------------------------------------------------------------------- /docs/guide/protocols/http/timeouts.md: -------------------------------------------------------------------------------- 1 | #### Timeouts 2 | 3 | By default, JMeter uses system default configurations for connection and response timeouts (maximum time for a connection to be established or a server response after a request, before it fails). This is might make the test behave different depending on the machine where it runs. To avoid this, it is recommended to always set these values. Here is an example: 4 | 5 | ```java 6 | testPlan( 7 | httpDefaults() 8 | .connectionTimeout(Duration.ofSeconds(10)) 9 | .responseTimeout(Duration.ofMinutes(1)), 10 | threadGroup(2, 10, 11 | httpSampler("http://my.service") 12 | ) 13 | ) 14 | ``` 15 | 16 | ::: warning 17 | Currently we are using same defaults as JMeter to avoid breaking existing test plans executions, but in a future major version we plan to change default setting to avoid the common pitfall previously mentioned. 18 | ::: 19 | -------------------------------------------------------------------------------- /docs/guide/protocols/index.md: -------------------------------------------------------------------------------- 1 | ## Protocols 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/guide/recorder/config-ide-autocomplete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/docs/guide/recorder/config-ide-autocomplete.png -------------------------------------------------------------------------------- /docs/guide/recorder/jmdsl-recorder.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/docs/guide/recorder/jmdsl-recorder.gif -------------------------------------------------------------------------------- /docs/guide/reporting/dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/docs/guide/reporting/dashboard.png -------------------------------------------------------------------------------- /docs/guide/reporting/index.md: -------------------------------------------------------------------------------- 1 | ## Reporting 2 | 3 | Once you have a test plan you would usually want to be able to analyze the collected information. This section contains several ways to achieve this. 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/guide/reporting/real-time/datadog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/docs/guide/reporting/real-time/datadog.png -------------------------------------------------------------------------------- /docs/guide/reporting/real-time/elasticsearch/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | es-bootstrap: 4 | build: ./elasticsearch-bootstrap 5 | 6 | elasticsearch: 7 | image: docker.elastic.co/elasticsearch/elasticsearch:7.14.0 8 | ports: 9 | - '9200:9200' 10 | - '9300:9300' 11 | volumes: 12 | - elasticsearch-data:/usr/share/elasticsearch/data 13 | environment: 14 | - discovery.type=single-node 15 | grafana: 16 | image: grafana/grafana:8.1.1 17 | ports: 18 | - '3000:3000' 19 | volumes: 20 | - grafana-data:/var/lib/grafana 21 | - ./grafana-provisioning/:/etc/grafana/provisioning 22 | depends_on: 23 | - elasticsearch 24 | environment: 25 | - GF_SECURITY_ADMIN_USER=admin 26 | - GF_SECURITY_ADMIN_PASSWORD=1234 27 | - GF_DASHBOARDS_DEFAULT_HOME_DASHBOARD_PATH=/etc/grafana/provisioning/dashboards/jmeter.json 28 | volumes: 29 | elasticsearch-data: 30 | grafana-data: 31 | -------------------------------------------------------------------------------- /docs/guide/reporting/real-time/elasticsearch/elasticsearch-bootstrap/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | RUN apt-get update \ 4 | && apt-get install -y curl 5 | 6 | RUN curl -O https://raw.githubusercontent.com/toschneck/wait-for-it/master/wait-for-it.sh \ 7 | && chmod +x wait-for-it.sh 8 | 9 | COPY index-template.json . 10 | 11 | CMD ["sh", "-c", "/wait-for-it.sh -t 60 elasticsearch:9200 && curl -X PUT 'elasticsearch:9200/_template/jmeter?pretty' -H 'Content-Type: application/json' --data-binary '@/index-template.json' && curl -X PUT elasticsearch:9200/jmeter"] 12 | -------------------------------------------------------------------------------- /docs/guide/reporting/real-time/elasticsearch/grafana-provisioning/dashboards/dashboard.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | providers: 3 | - name: JMeter Dashboards 4 | allowUiUpdates: true 5 | options: 6 | path: /etc/grafana/provisioning/dashboards -------------------------------------------------------------------------------- /docs/guide/reporting/real-time/elasticsearch/grafana-provisioning/datasources/datasource.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | datasources: 3 | - name: Elasticsearch 4 | type: elasticsearch 5 | access: proxy 6 | url: http://elasticsearch:9200 7 | database: jmeter 8 | isDefault: true 9 | editable: true 10 | jsonData: 11 | esVersion: "7.10.0" 12 | timeField: Timestamp 13 | -------------------------------------------------------------------------------- /docs/guide/reporting/real-time/graphite.md: -------------------------------------------------------------------------------- 1 | #### Graphite 2 | 3 | In a similar fashion to InfluxDB, you can use Graphite and Grafana. Here is an example test plan using the `graphiteListener`: 4 | 5 | ```java 6 | import static org.assertj.core.api.Assertions.assertThat; 7 | import static us.abstracta.jmeter.javadsl.JmeterDsl.*; 8 | 9 | import java.io.IOException; 10 | import java.time.Duration; 11 | import org.junit.jupiter.api.Test; 12 | import us.abstracta.jmeter.javadsl.core.TestPlanStats; 13 | 14 | public class PerformanceTest { 15 | 16 | @Test 17 | public void testPerformance() throws IOException { 18 | TestPlanStats stats = testPlan( 19 | threadGroup(2, 10, 20 | httpSampler("http://my.service") 21 | ), 22 | graphiteListener("localhost:2004") 23 | ).run(); 24 | assertThat(stats.overall().sampleTimePercentile99()).isLessThan(Duration.ofSeconds(5)); 25 | } 26 | 27 | } 28 | ``` 29 | 30 | As in the InfluxDB scenario, you can try it locally by running `docker-compose up` (previously [installing Docker](https://docs.docker.com/get-docker/) in your machine) inside [this directory](/docs/guide/reporting/real-time/graphite). After containers are started, you can follow the same steps as in the InfluxDB scenario. 31 | 32 | ::: warning 33 | Use the provided `docker-compose` settings for local tests only. It uses weak credentials and is not properly configured for production purposes. 34 | ::: 35 | 36 | ::: warning 37 | `graphiteListener` is configured to use Pickle Protocol, and port 2004, by default. This is more efficient than text plain protocol, which is the one used by default by JMeter. 38 | ::: 39 | -------------------------------------------------------------------------------- /docs/guide/reporting/real-time/graphite/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | graphite: 4 | image: graphiteapp/graphite-statsd:1.1.10-5 5 | ports: 6 | - '2003:2003' 7 | - '2004:2004' 8 | - '8080:80' 9 | volumes: 10 | - ./graphite-conf/carbon.conf:/opt/graphite/conf/carbon.conf 11 | - ./graphite-conf/storage-schemas.conf:/opt/graphite/conf/storage-schemas.conf 12 | - graphite-data:/opt/graphite/storage/whisper 13 | grafana: 14 | image: grafana/grafana:8.1.1 15 | ports: 16 | - '3000:3000' 17 | volumes: 18 | - grafana-data:/var/lib/grafana 19 | - ./grafana-provisioning/:/etc/grafana/provisioning 20 | depends_on: 21 | - graphite 22 | environment: 23 | - GF_SECURITY_ADMIN_USER=admin 24 | - GF_SECURITY_ADMIN_PASSWORD=1234 25 | - GF_DASHBOARDS_DEFAULT_HOME_DASHBOARD_PATH=/etc/grafana/provisioning/dashboards/jmeter.json 26 | volumes: 27 | graphite-data: 28 | grafana-data: 29 | -------------------------------------------------------------------------------- /docs/guide/reporting/real-time/graphite/grafana-provisioning/dashboards/dashboard.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | providers: 3 | - name: JMeter Dashboards 4 | allowUiUpdates: true 5 | options: 6 | path: /etc/grafana/provisioning/dashboards -------------------------------------------------------------------------------- /docs/guide/reporting/real-time/graphite/grafana-provisioning/datasources/datasource.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | datasources: 3 | - name: Graphite 4 | type: graphite 5 | access: proxy 6 | url: http://graphite:80 7 | isDefault: true 8 | editable: true 9 | jsonData: 10 | graphiteVersion: "1.1" 11 | -------------------------------------------------------------------------------- /docs/guide/reporting/real-time/graphite/graphite-conf/storage-schemas.conf: -------------------------------------------------------------------------------- 1 | # Schema definitions for Whisper files. Entries are scanned in order, 2 | # and first match wins. This file is scanned for changes every 60 seconds. 3 | # 4 | # Definition Syntax: 5 | # 6 | # [name] 7 | # pattern = regex 8 | # retentions = timePerPoint:timeToStore, timePerPoint:timeToStore, ... 9 | # 10 | # Remember: To support accurate aggregation from higher to lower resolution 11 | # archives, the precision of a longer retention archive must be 12 | # cleanly divisible by precision of next lower retention archive. 13 | # 14 | # Valid: 60s:7d,300s:30d (300/60 = 5) 15 | # Invalid: 180s:7d,300s:30d (300/180 = 3.333) 16 | # 17 | 18 | # Carbon's internal metrics. This entry should match what is specified in 19 | # CARBON_METRIC_PREFIX and CARBON_METRIC_INTERVAL settings 20 | [carbon] 21 | pattern = ^carbon\. 22 | retentions = 10s:6h,1m:90d 23 | 24 | # Changed this since for some reason when set to aggregate every 10 seconds, it only reports counts 25 | # as 1 per every 10 seconds instead of the actual value (as if sum aggregate was not working).1 26 | # Jmeter Graphite Listener sends metrics in every second. Additionally, is nice to have as much 27 | # granularity as possible. 28 | [default_1sec_for_7day] 29 | pattern = .* 30 | retentions = 1s:7d,1m:30d -------------------------------------------------------------------------------- /docs/guide/reporting/real-time/index.md: -------------------------------------------------------------------------------- 1 | ### Real-time metrics visualization and historic data storage 2 | 3 | When running tests with JMeter (and in particular with jmeter-java-dsl) a usual requirement is to be able to store such test runs in a persistent database to, later on, review such metrics, and compare different test runs. Additionally, jmeter-java-dsl only provides some summary data of a test run in the console while it is running, but, since it doesn't provide any sort of UI, this doesn't allow you to easily analyze such information as it can be done in JMeter GUI. 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /docs/guide/reporting/real-time/influxdb/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | influxdb: 4 | image: influxdb:1.8 5 | ports: 6 | - '8086:8086' 7 | volumes: 8 | - influxdb-data:/var/lib/influxdb 9 | environment: 10 | - INFLUXDB_DB=jmeter 11 | - INFLUXDB_ADMIN_USER=admin 12 | - INFLUXDB_ADMIN_PASSWORD=admin 13 | grafana: 14 | image: grafana/grafana:8.1.1 15 | ports: 16 | - '3000:3000' 17 | volumes: 18 | - grafana-data:/var/lib/grafana 19 | - ./grafana-provisioning/:/etc/grafana/provisioning 20 | depends_on: 21 | - influxdb 22 | environment: 23 | - GF_SECURITY_ADMIN_USER=admin 24 | - GF_SECURITY_ADMIN_PASSWORD=1234 25 | - GF_DASHBOARDS_DEFAULT_HOME_DASHBOARD_PATH=/etc/grafana/provisioning/dashboards/jmeter.json 26 | volumes: 27 | influxdb-data: 28 | grafana-data: 29 | -------------------------------------------------------------------------------- /docs/guide/reporting/real-time/influxdb/grafana-provisioning/dashboards/dashboard.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | providers: 3 | - name: JMeter Dashboards 4 | allowUiUpdates: true 5 | options: 6 | path: /etc/grafana/provisioning/dashboards -------------------------------------------------------------------------------- /docs/guide/reporting/real-time/influxdb/grafana-provisioning/datasources/datasource.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | datasources: 3 | - name: InfluxDB 4 | type: influxdb 5 | access: proxy 6 | url: http://influxdb:8086 7 | database: jmeter 8 | user: admin 9 | password: admin 10 | isDefault: true 11 | editable: true 12 | -------------------------------------------------------------------------------- /docs/guide/reporting/real-time/influxdb/grafana.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/docs/guide/reporting/real-time/influxdb/grafana.png -------------------------------------------------------------------------------- /docs/guide/reporting/real-time/prometheus/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | prometheus: 3 | image: prom/prometheus:v2.51.2 4 | ports: 5 | - '9090:9090' 6 | volumes: 7 | - prometheus-data:/prometheus 8 | - ./prometheus.yml:/etc/prometheus/prometheus.yml 9 | grafana: 10 | image: grafana/grafana:10.4.2 11 | ports: 12 | - '3000:3000' 13 | volumes: 14 | - grafana-data:/var/lib/grafana 15 | - ./grafana-provisioning/:/etc/grafana/provisioning 16 | depends_on: 17 | - prometheus 18 | environment: 19 | - GF_SECURITY_ADMIN_USER=admin 20 | - GF_SECURITY_ADMIN_PASSWORD=1234 21 | - GF_DASHBOARDS_DEFAULT_HOME_DASHBOARD_PATH=/etc/grafana/provisioning/dashboards/jmeter.json 22 | volumes: 23 | prometheus-data: 24 | grafana-data: 25 | -------------------------------------------------------------------------------- /docs/guide/reporting/real-time/prometheus/grafana-provisioning/dashboards/dashboard.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | providers: 3 | - name: JMeter Dashboards 4 | allowUiUpdates: true 5 | options: 6 | path: /etc/grafana/provisioning/dashboards -------------------------------------------------------------------------------- /docs/guide/reporting/real-time/prometheus/grafana-provisioning/datasources/datasource.yml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | datasources: 3 | - name: Prometheus 4 | type: prometheus 5 | access: proxy 6 | url: http://prometheus:9090 7 | isDefault: true 8 | editable: true 9 | jsonData: 10 | httpMethod: "POST" 11 | queryTimeout: "10s" 12 | timeInterval: "5s" 13 | -------------------------------------------------------------------------------- /docs/guide/reporting/real-time/prometheus/prometheus.yml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 5s 3 | evaluation_interval: 5s 4 | scrape_configs: 5 | - job_name: "prometheus" 6 | static_configs: 7 | - targets: ["localhost:9090"] 8 | - job_name: "jmeter" 9 | static_configs: 10 | - targets: ["host.docker.internal:9270"] -------------------------------------------------------------------------------- /docs/guide/request-generation/counter.md: -------------------------------------------------------------------------------- 1 | ### Counter 2 | 3 | In scenarios that you need unique value for each request, for example for id parameters, you can use `counter` which provides easy means to have an auto incremental value that can be used in requests. 4 | 5 | Here is an example: 6 | 7 | ```java 8 | testPlan( 9 | threadGroup(1, 10, 10 | counter("USER_ID") 11 | .startingValue(1000), // will generate 1000, 1001, 1002... 12 | httpSampler(wiremockUri + "/${USER_ID}") 13 | ) 14 | ).run(); 15 | ``` 16 | 17 | Check [DslCounter](/jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/configs/DslCounter.java) for more details. 18 | -------------------------------------------------------------------------------- /docs/guide/request-generation/index.md: -------------------------------------------------------------------------------- 1 | ## Requests generation 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/guide/request-generation/loops/index.md: -------------------------------------------------------------------------------- 1 | ### Loops 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /docs/guide/request-generation/loops/runtime-controller.md: -------------------------------------------------------------------------------- 1 | #### Iterating for a given period 2 | 3 | In some scenarios you might want to execute a given logic until all the steps are executed or a given period of time has passed. In these scenarios you can use `runtimeController` which stops executing children elements when a specified time is reached. 4 | 5 | Here is an example which makes requests to a page until token expires by using `runtimeController` in combination with `whileController`. 6 | 7 | ```java 8 | import static org.assertj.core.api.Assertions.assertThat; 9 | import static us.abstracta.jmeter.javadsl.JmeterDsl.*; 10 | 11 | import java.io.IOException; 12 | import java.time.Duration; 13 | import org.junit.jupiter.api.Test; 14 | import us.abstracta.jmeter.javadsl.core.TestPlanStats; 15 | 16 | public class PerformanceTest { 17 | 18 | @Test 19 | public void testPerformance() throws IOException { 20 | Duration tokenExpiration = Duration.ofSeconds(5); 21 | TestPlanStats stats = testPlan( 22 | threadGroup(2, 10, 23 | httpSampler("http://my.service/token"), 24 | runtimeController(tokenExpiration, 25 | whileController("true", 26 | httpSampler("http://my.service/accounts") 27 | ) 28 | ) 29 | ) 30 | ).run(); 31 | assertThat(stats.overall().sampleTimePercentile99()).isLessThan(Duration.ofSeconds(5)); 32 | } 33 | 34 | } 35 | ``` 36 | 37 | Check [DslRuntimeController](/jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/controllers/DslRuntimeController.java) for more details. 38 | -------------------------------------------------------------------------------- /docs/guide/request-generation/percent-controller.md: -------------------------------------------------------------------------------- 1 | ### Execute part of a test plan part a fraction of the times 2 | 3 | In some cases, you may want to execute a given part of the test plan not in every iteration, and only for a given percent of times, to emulate certain probabilistic nature of the flow the users execute. 4 | 5 | In such scenarios, you may use `percentController`, which uses JMeter Throughput Controller to achieve exactly that. 6 | 7 | Here is an example: 8 | 9 | ```java 10 | import static org.assertj.core.api.Assertions.assertThat; 11 | import static us.abstracta.jmeter.javadsl.JmeterDsl.*; 12 | 13 | import java.time.Duration; 14 | import org.junit.jupiter.api.Test; 15 | import us.abstracta.jmeter.javadsl.core.TestPlanStats; 16 | 17 | public class PerformanceTest { 18 | 19 | @Test 20 | public void testPerformance() throws Exception { 21 | TestPlanStats stats = testPlan( 22 | threadGroup(2, 10, 23 | percentController(40, // run this 40% of the times 24 | httpSampler("http://my.service/status"), 25 | httpSampler("http://my.service/poll")), 26 | percentController(70, // run this 70% of the times 27 | httpSampler("http://my.service/items")) 28 | ) 29 | ).run(); 30 | assertThat(stats.overall().sampleTimePercentile99()).isLessThan(Duration.ofSeconds(5)); 31 | } 32 | 33 | } 34 | ``` 35 | 36 | Check [PercentController](/jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/controllers/PercentController.java) for more details. 37 | -------------------------------------------------------------------------------- /docs/guide/request-generation/timers/index.md: -------------------------------------------------------------------------------- 1 | ### Timers 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/guide/request-generation/timers/not-synchronized-samples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/docs/guide/request-generation/timers/not-synchronized-samples.png -------------------------------------------------------------------------------- /docs/guide/request-generation/timers/synchronized-samples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/docs/guide/request-generation/timers/synchronized-samples.png -------------------------------------------------------------------------------- /docs/guide/request-generation/timers/synchronizing-timer.md: -------------------------------------------------------------------------------- 1 | #### Requests synchronization 2 | 3 | Usually, samples generated by different threads in a test plan thread group start deviating from each other according to the different durations each of them may experience. 4 | 5 | Here is a diagram depicting this behavior, extracted from [this nice example](https://github.com/abstracta/jmeter-java-dsl/discussions/204) provided by one of JMeter DSL users: 6 | 7 | ![not synchronized samples in 2 threads and 3 iterations](./not-synchronized-samples.png) 8 | 9 | In most cases this is ok. But, if you want to generate batches of simultaneous requests to a system under test, this variability will prevent you from getting the expected behavior. 10 | 11 | So, to synchronize requests, by holding some of them until all are in sync, like in this diagram: 12 | 13 | ![synchronized samples in 2 threads and 3 iterations](./synchronized-samples.png) 14 | 15 | You can use `synchronizingTimer` like in the following example: 16 | 17 | ```java 18 | testPlan( 19 | threadGroup(2, 3, 20 | httpSample("https://mysite"), 21 | synchronizingTimer() 22 | ) 23 | ) 24 | ``` 25 | -------------------------------------------------------------------------------- /docs/guide/request-generation/weighted-switch-controller.md: -------------------------------------------------------------------------------- 1 | ### Switch between test plan parts with a given probability 2 | 3 | In some cases, you need to switch in a test plan between different behaviors assigning to them different probabilities. The main difference between this need and the previous one is that in each iteration you have to execute one of the parts, while in the previous case you might get multiple or no part executed on a given iteration. 4 | 5 | For this scenario you can use `weightedSwitchCotroller`, like in this example: 6 | 7 | ```java 8 | import static org.assertj.core.api.Assertions.assertThat; 9 | import static us.abstracta.jmeter.javadsl.JmeterDsl.*; 10 | 11 | import java.io.IOException; 12 | import java.time.Duration; 13 | import org.junit.jupiter.api.Test; 14 | import us.abstracta.jmeter.javadsl.core.TestPlanStats; 15 | 16 | public class PerformanceTest { 17 | 18 | @Test 19 | public void testPerformance() throws IOException { 20 | TestPlanStats stats = testPlan( 21 | threadGroup(2, 10, 22 | weightedSwitchController() 23 | .child(30, httpSampler("https://myservice/1")) // will run 30/(30+20)=60% of the iterations 24 | .child(20, httpSampler("https://myservice/2")) // will run 20/(30+20)=40% of the iterations 25 | ) 26 | ).run(); 27 | assertThat(stats.overall().sampleTimePercentile99()).isLessThan(Duration.ofSeconds(5)); 28 | } 29 | 30 | } 31 | ``` 32 | 33 | [DslWeightedSwitchController](/jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/controllers/DslWeightedSwitchController.java) for more details. 34 | -------------------------------------------------------------------------------- /docs/guide/response-processing/correlation/boundary-extractor.md: -------------------------------------------------------------------------------- 1 | #### Boundaries based extraction 2 | 3 | Regular expressions are quite powerful and flexible, but also are complex and performance might not be optimal in some scenarios. When you know that desired extraction is always surrounded by some specific text that never varies, then you can use `boundaryExtractor` which is simpler and in many cases more performant: 4 | 5 | ```java 6 | import static org.assertj.core.api.Assertions.assertThat; 7 | import static us.abstracta.jmeter.javadsl.JmeterDsl.*; 8 | 9 | import java.io.IOException; 10 | import java.time.Duration; 11 | import org.apache.http.entity.ContentType; 12 | import org.junit.jupiter.api.Test; 13 | import us.abstracta.jmeter.javadsl.core.TestPlanStats; 14 | 15 | public class PerformanceTest { 16 | 17 | @Test 18 | public void testPerformance() throws IOException { 19 | TestPlanStats stats = testPlan( 20 | threadGroup(2, 10, 21 | httpSampler("http://my.service/accounts") 22 | .post("{\"name\": \"John Doe\"}", ContentType.APPLICATION_JSON) 23 | .children( 24 | boundaryExtractor("ACCOUNT_ID", "\"id\":\"", "\"") 25 | ), 26 | httpSampler("http://my.service/accounts/${ACCOUNT_ID}") 27 | ) 28 | ).run(); 29 | assertThat(stats.overall().sampleTimePercentile99()).isLessThan(Duration.ofSeconds(5)); 30 | } 31 | 32 | } 33 | ``` 34 | 35 | Check [DslBoundaryExtractor](/jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/postprocessors/DslBoundaryExtractor.java) for more details and additional options. 36 | -------------------------------------------------------------------------------- /docs/guide/response-processing/correlation/index.md: -------------------------------------------------------------------------------- 1 | ### Use part of a response in a subsequent request (aka correlation) 2 | 3 | It is a usual requirement while creating a test plan for an application to be able to use part of a response (e.g.: a generated ID, token, etc.) in a subsequent request. This can be easily achieved using JMeter extractors and variables. 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /docs/guide/response-processing/correlation/json-extractor.md: -------------------------------------------------------------------------------- 1 | #### JSON extraction 2 | 3 | When the response of a request is JSON, then you can use `jsonExtractor` like in the following example: 4 | 5 | ```java 6 | import static org.assertj.core.api.Assertions.assertThat; 7 | import static us.abstracta.jmeter.javadsl.JmeterDsl.*; 8 | 9 | import java.io.IOException; 10 | import java.time.Duration; 11 | import org.apache.http.entity.ContentType; 12 | import org.junit.jupiter.api.Test; 13 | import us.abstracta.jmeter.javadsl.core.TestPlanStats; 14 | 15 | public class PerformanceTest { 16 | 17 | @Test 18 | public void testPerformance() throws IOException { 19 | TestPlanStats stats = testPlan( 20 | threadGroup(2, 10, 21 | httpSampler("http://my.service/accounts") 22 | .post("{\"name\": \"John Doe\"}", ContentType.APPLICATION_JSON) 23 | .children( 24 | jsonExtractor("ACCOUNT_ID", "id") 25 | ), 26 | httpSampler("http://my.service/accounts/${ACCOUNT_ID}") 27 | ) 28 | ).run(); 29 | assertThat(stats.overall().sampleTimePercentile99()).isLessThan(Duration.ofSeconds(5)); 30 | } 31 | 32 | } 33 | ``` 34 | 35 | ::: tip 36 | By default this element uses JMeter JSON [JMESPath](https://jmespath.org/) Extractor element, and in consequence JMESPath as query language. 37 | 38 | If you want to use JMeter JSON Extractor element, and in consequence [JSONPath](https://github.com/json-path/JsonPath) as query language, you can simply use `.queryLanguage(JsonQueryLanguage.JSON_PATH)` and a JSONPath query. 39 | ::: 40 | -------------------------------------------------------------------------------- /docs/guide/response-processing/correlation/regex-extractor.md: -------------------------------------------------------------------------------- 1 | #### Regular expressions extraction 2 | 3 | Here is an example with jmeter-java-dsl using regular expressions: 4 | 5 | ```java 6 | import static org.assertj.core.api.Assertions.assertThat; 7 | import static us.abstracta.jmeter.javadsl.JmeterDsl.*; 8 | 9 | import java.io.IOException; 10 | import java.time.Duration; 11 | import org.apache.http.entity.ContentType; 12 | import org.junit.jupiter.api.Test; 13 | import us.abstracta.jmeter.javadsl.core.TestPlanStats; 14 | 15 | public class PerformanceTest { 16 | 17 | @Test 18 | public void testPerformance() throws IOException { 19 | TestPlanStats stats = testPlan( 20 | threadGroup(2, 10, 21 | httpSampler("http://my.service/accounts") 22 | .post("{\"name\": \"John Doe\"}", ContentType.APPLICATION_JSON) 23 | .children( 24 | regexExtractor("ACCOUNT_ID", "\"id\":\"([^\"]+)\"") 25 | ), 26 | httpSampler("http://my.service/accounts/${ACCOUNT_ID}") 27 | ) 28 | ).run(); 29 | assertThat(stats.overall().sampleTimePercentile99()).isLessThan(Duration.ofSeconds(5)); 30 | } 31 | 32 | } 33 | ``` 34 | 35 | Check [DslRegexExtractor](/jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/postprocessors/DslRegexExtractor.java) for more details and additional options. 36 | -------------------------------------------------------------------------------- /docs/guide/response-processing/index.md: -------------------------------------------------------------------------------- 1 | ## Response processing 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /docs/guide/scale/azure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/docs/guide/scale/azure.png -------------------------------------------------------------------------------- /docs/guide/scale/blazemeter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/docs/guide/scale/blazemeter.png -------------------------------------------------------------------------------- /docs/guide/scale/distributed/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | test: 4 | image: maven:3.8 5 | working_dir: /usr/src/test 6 | volumes: 7 | - ./test:/usr/src/test 8 | - ./rmi_keystore.jks:/usr/src/test/rmi_keystore.jks 9 | - ~/.m2:/root/.m2 10 | command: mvn clean test 11 | server: 12 | build: jmeter 13 | volumes: 14 | - ./rmi_keystore.jks:/opt/jmeter/rmi_keystore.jks 15 | command: jmeter-server -Dserver.rmi.localport=2020 -Djava.rmi.server.hostname=server 16 | -------------------------------------------------------------------------------- /docs/guide/scale/distributed/jmeter/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM eclipse-temurin:8 2 | 3 | ENV JMETER_VERSION=5.5 4 | ENV JMETER_HOME=/opt/jmeter 5 | ENV JMETER_TGZ_PATH=/tmp/jmeter.tgz 6 | 7 | WORKDIR ${JMETER_HOME} 8 | 9 | RUN curl -L -s -o ${JMETER_TGZ_PATH} https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-${JMETER_VERSION}.tgz \ 10 | && tar -xzf ${JMETER_TGZ_PATH} \ 11 | && mv apache-jmeter-${JMETER_VERSION}/* . \ 12 | && rm -r apache-jmeter-${JMETER_VERSION} \ 13 | && rm ${JMETER_TGZ_PATH} 14 | 15 | ENV PATH $PATH:$JMETER_HOME/bin 16 | -------------------------------------------------------------------------------- /docs/guide/scale/distributed/rmi_keystore.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/docs/guide/scale/distributed/rmi_keystore.jks -------------------------------------------------------------------------------- /docs/guide/scale/distributed/test/rmi_keystore.jks: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/guide/scale/distributed/test/src/test/java/PerformanceTest.java: -------------------------------------------------------------------------------- 1 | import static org.assertj.core.api.Assertions.assertThat; 2 | import static us.abstracta.jmeter.javadsl.JmeterDsl.*; 3 | 4 | import org.junit.jupiter.api.Test; 5 | import us.abstracta.jmeter.javadsl.core.TestPlanStats; 6 | import us.abstracta.jmeter.javadsl.core.engines.DistributedJmeterEngine; 7 | 8 | public class PerformanceTest { 9 | 10 | @Test 11 | public void shouldGetExpectedCountWhenRunTestInRemoteEngine() throws Exception { 12 | TestPlanStats stats = testPlan( 13 | threadGroup(1, 1, 14 | httpSampler("https://myservice") 15 | ) 16 | ).runIn(new DistributedJmeterEngine("server:1099")); 17 | assertThat(stats.overall().samplesCount()).isEqualTo(1); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /docs/guide/scale/index.md: -------------------------------------------------------------------------------- 1 | ## Run test at scale 2 | 3 | Running a load test from one machine is not always enough, since you are limited to the machine's hardware capabilities. Sometimes, is necessary to run the test using a cluster of machines to be able to generate enough load for the system under test. 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/guide/scale/octoperf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/docs/guide/scale/octoperf.png -------------------------------------------------------------------------------- /docs/guide/setup.md: -------------------------------------------------------------------------------- 1 | ## Setup 2 | 3 | To use the DSL just include it in your project: 4 | 5 | :::: code-group 6 | ::: code-group-item Maven 7 | ```xml 8 | 9 | us.abstracta.jmeter 10 | jmeter-java-dsl 11 | 2.2 12 | test 13 | 14 | ``` 15 | ::: 16 | ::: code-group-item Gradle 17 | ```groovy 18 | testImplementation("us.abstracta.jmeter:jmeter-java-dsl:2.2") { 19 | exclude("org.apache.jmeter", "bom") 20 | } 21 | ``` 22 | ::: 23 | :::: 24 | 25 | ::: tip 26 | [Here](https://github.com/abstracta/jmeter-java-dsl-sample) is a sample project in case you want to start one from scratch. 27 | ::: -------------------------------------------------------------------------------- /docs/guide/test-resources.md: -------------------------------------------------------------------------------- 1 | ## Test resources 2 | 3 | When working with tests in maven projects, even gradle in some scenarios, it is usually necessary to use files hosted in `src/test/resources`. For example CSV files for `csvDataSet`, a file to be used by an `httpSampler`, some JSON for comparison, etc. The DSL provides `testResource` as a handy shortcut for such scenarios. Here is a simple example: 4 | 5 | ```java 6 | import static us.abstracta.jmeter.javadsl.JmeterDsl.*; 7 | 8 | import java.io.IOException; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class PerformanceTest { 12 | 13 | @Test 14 | public void testProperties() throws IOException { 15 | testPlan( 16 | csvDataSet(testResource("users.csv")), // gets users info from src/test/resources/users.csv 17 | threadGroup(1, 1, 18 | httpSampler("http://myservice.test/users/${USER_ID}") 19 | ) 20 | ).run(); 21 | } 22 | 23 | } 24 | ``` 25 | 26 | Check [TestResource](/jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/util/TestResource.java) for some further details. 27 | 28 | -------------------------------------------------------------------------------- /docs/guide/thread-groups/images/rps-thread-group-timeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/docs/guide/thread-groups/images/rps-thread-group-timeline.png -------------------------------------------------------------------------------- /docs/guide/thread-groups/images/ultimate-thread-group-gui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/docs/guide/thread-groups/images/ultimate-thread-group-gui.png -------------------------------------------------------------------------------- /docs/guide/thread-groups/images/ultimate-thread-group-timeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/docs/guide/thread-groups/images/ultimate-thread-group-timeline.png -------------------------------------------------------------------------------- /docs/guide/thread-groups/index.md: -------------------------------------------------------------------------------- 1 | ## Advanced threads configuration 2 | 3 | jmeter-java-dsl provides two simple ways of creating thread groups which are used in most scenarios: 4 | 5 | * specifying threads and the number of iterations each thread should execute before ending the test plan 6 | * specifying threads and duration for which each thread should execute before the test plan ends 7 | 8 | This is how they look in code: 9 | 10 | ```java 11 | threadGroup(10, 20, ...) // 10 threads for 20 iterations each 12 | threadGroup(10, Duration.ofSeconds(20), ...) // 10 threads for 20 seconds each 13 | ``` 14 | 15 | But these options are not good when working with many threads or when trying to configure some complex test scenarios (like when doing incremental or peak tests). 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/guide/thread-groups/order.md: -------------------------------------------------------------------------------- 1 | ### Thread groups order 2 | 3 | By default, when you add multiple thread groups to a test plan, JMeter will run them all in parallel. This is a very helpful behavior in many cases, but in some others, you may want to run them sequentially (one after the other). To achieve this you can just use `sequentialThreadGroups()` test plan method. 4 | -------------------------------------------------------------------------------- /docs/guide/variables-and-properties/index.md: -------------------------------------------------------------------------------- 1 | ## JMeter variables & properties 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jmeter-java-dsl", 3 | "version": "1.0.0", 4 | "description": "Simple JMeter performance tests API", 5 | "main": "index.js", 6 | "repository": "https://github.com/abstracta/jmeter-java-dsl", 7 | "license": "Apache-2.0", 8 | "devDependencies": { 9 | "@fortawesome/fontawesome-svg-core": "^6.4.2", 10 | "@fortawesome/free-brands-svg-icons": "^6.4.2", 11 | "@fortawesome/free-solid-svg-icons": "^6.4.2", 12 | "@fortawesome/vue-fontawesome": "^3.0.3", 13 | "@vuepress/cli": "2.0.0-beta.64", 14 | "@vuepress/client": "2.0.0-beta.64", 15 | "@vuepress/plugin-container": "2.0.0-beta.64", 16 | "@vuepress/plugin-medium-zoom": "2.0.0-beta.64", 17 | "@vuepress/plugin-register-components": "2.0.0-beta.64", 18 | "@vuepress/plugin-search": "2.0.0-beta.64", 19 | "@vuepress/shared": "2.0.0-beta.64", 20 | "@vuepress/theme-default": "2.0.0-beta.64", 21 | "@vuepress/utils": "2.0.0-beta.64", 22 | "markdown-it-replace-link": "^1.2.0", 23 | "vue": "^3.3.7", 24 | "vue-router": "^4.2.5", 25 | "vuepress": "2.0.0-beta.64", 26 | "vuepress-plugin-copy-code2": "2.0.0-beta.230", 27 | "vuepress-plugin-md-enhance": "2.0.0-beta.230" 28 | }, 29 | "scripts": { 30 | "dev": "vuepress dev . --clean-cache --clean-temp", 31 | "build": "vuepress build . --clean-cache --clean-temp" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /docs/support/abstracta-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/docs/support/abstracta-logo.png -------------------------------------------------------------------------------- /docs/support/azure-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/docs/support/azure-logo.png -------------------------------------------------------------------------------- /docs/support/blazemeter-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/docs/support/blazemeter-logo.png -------------------------------------------------------------------------------- /docs/support/octoperf-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/docs/support/octoperf-logo.png -------------------------------------------------------------------------------- /jmeter-java-dsl-azure/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | us.abstracta.jmeter 8 | jmeter-java-dsl-parent 9 | 2.3-SNAPSHOT 10 | ../pom.xml 11 | 12 | jmeter-java-dsl-azure 13 | 14 | ${project.artifactId} 15 | Module which allows to easily run jmeter-java-dsl test plans at scale in 16 | Azure Load Testing. 17 | 18 | 19 | 20 | 21 | us.abstracta.jmeter 22 | jmeter-java-dsl-base-remote-engine 23 | ${project.version} 24 | 25 | 26 | 27 | 28 | 29 | 30 | src/main/resources 31 | true 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /jmeter-java-dsl-azure/src/main/java/us/abstracta/jmeter/javadsl/azure/api/AzureResource.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.azure.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonIgnore; 5 | import com.fasterxml.jackson.annotation.JsonProperty; 6 | 7 | public abstract class AzureResource { 8 | 9 | @JsonIgnore 10 | protected AzureResourceProperties properties; 11 | 12 | protected AzureResource(AzureResourceProperties properties) { 13 | this.properties = properties; 14 | } 15 | 16 | @JsonIgnore 17 | public String getProvisioningState() { 18 | return properties.provisioningState; 19 | } 20 | 21 | public void setProvisioningState(String provisioningState) { 22 | properties.provisioningState = provisioningState; 23 | } 24 | 25 | @JsonIgnore 26 | public boolean isPendingProvisioning() { 27 | String lowerState = properties.provisioningState.toLowerCase(); 28 | return !("succeeded".equals(lowerState) || "failed".equals(lowerState) || "canceled".equals( 29 | lowerState)); 30 | } 31 | 32 | @JsonIgnore 33 | public boolean isProvisioned() { 34 | return "succeeded".equalsIgnoreCase(properties.provisioningState); 35 | } 36 | 37 | public static class AzureResourceProperties { 38 | 39 | private String provisioningState; 40 | 41 | @JsonCreator 42 | public AzureResourceProperties(@JsonProperty("provisioningState") String provisioningState) { 43 | this.provisioningState = provisioningState; 44 | } 45 | 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /jmeter-java-dsl-azure/src/main/java/us/abstracta/jmeter/javadsl/azure/api/FileInfo.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.azure.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonIgnore; 5 | import com.fasterxml.jackson.annotation.JsonProperty; 6 | 7 | public class FileInfo { 8 | 9 | private final String fileName; 10 | private final String validationStatus; 11 | private final String validationFailureDetails; 12 | 13 | @JsonCreator 14 | public FileInfo(@JsonProperty("fileName") String fileName, 15 | @JsonProperty("validationStatus") String validationStatus, 16 | @JsonProperty("validationFailureDetails") String validationFailureDetails) { 17 | this.fileName = fileName; 18 | this.validationStatus = validationStatus; 19 | this.validationFailureDetails = validationFailureDetails; 20 | } 21 | 22 | public String getFileName() { 23 | return fileName; 24 | } 25 | 26 | public String getValidationStatus() { 27 | return validationStatus; 28 | } 29 | 30 | public String getValidationFailureDetails() { 31 | return validationFailureDetails; 32 | } 33 | 34 | @JsonIgnore 35 | public boolean isPendingValidation() { 36 | return validationStatus == null || "VALIDATION_INITIATED".equals(validationStatus) 37 | || "NOT_VALIDATED".equals(validationStatus); 38 | } 39 | 40 | @JsonIgnore 41 | public boolean isSuccessValidation() { 42 | return validationStatus == null || "VALIDATION_SUCCESS".equals(validationStatus) 43 | || "VALIDATION_NOT_REQUIRED".equals(validationStatus); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /jmeter-java-dsl-azure/src/main/java/us/abstracta/jmeter/javadsl/azure/api/Location.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.azure.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | public class Location { 7 | 8 | private final String name; 9 | 10 | @JsonCreator 11 | public Location(@JsonProperty("name") String name) { 12 | this.name = name; 13 | } 14 | 15 | public String getName() { 16 | return name; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /jmeter-java-dsl-azure/src/main/java/us/abstracta/jmeter/javadsl/azure/api/ResourceGroup.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.azure.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonIgnore; 5 | import com.fasterxml.jackson.annotation.JsonProperty; 6 | 7 | public class ResourceGroup extends AzureResource { 8 | 9 | @JsonIgnore 10 | private String name; 11 | private String location; 12 | @JsonIgnore 13 | private Subscription subscription; 14 | 15 | @JsonCreator 16 | public ResourceGroup(@JsonProperty("properties") AzureResourceProperties properties) { 17 | super(properties); 18 | } 19 | 20 | public ResourceGroup(String name, Location location, Subscription subscription) { 21 | this(new AzureResourceProperties(null)); 22 | this.name = name; 23 | this.location = location.getName(); 24 | this.subscription = subscription; 25 | } 26 | 27 | public String getName() { 28 | return name; 29 | } 30 | 31 | public void setName(String name) { 32 | this.name = name; 33 | } 34 | 35 | public Subscription getSubscription() { 36 | return subscription; 37 | } 38 | 39 | public void setSubscription(Subscription subscription) { 40 | this.subscription = subscription; 41 | } 42 | 43 | public String getLocation() { 44 | return location; 45 | } 46 | 47 | @JsonIgnore 48 | public String getUrl() { 49 | return subscription.getUrl() + "/resourceGroups/" + name; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /jmeter-java-dsl-azure/src/main/java/us/abstracta/jmeter/javadsl/azure/api/ResponseList.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.azure.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonIgnore; 5 | import com.fasterxml.jackson.annotation.JsonProperty; 6 | import java.util.List; 7 | import java.util.Optional; 8 | import java.util.stream.Stream; 9 | 10 | public class ResponseList { 11 | 12 | private final List value; 13 | 14 | @JsonCreator 15 | public ResponseList(@JsonProperty("value") List value) { 16 | this.value = value; 17 | } 18 | 19 | @JsonIgnore 20 | public Optional getFirstElement() { 21 | return value.isEmpty() ? Optional.empty() : Optional.of(value.get(0)); 22 | } 23 | 24 | public Stream stream() { 25 | return value.stream(); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /jmeter-java-dsl-azure/src/main/java/us/abstracta/jmeter/javadsl/azure/api/Secret.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.azure.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | public class Secret { 7 | 8 | private final SecretType type; 9 | private final String value; 10 | 11 | @JsonCreator 12 | public Secret(@JsonProperty("type") SecretType type, @JsonProperty("value") String value) { 13 | this.type = type; 14 | this.value = value; 15 | } 16 | 17 | public enum SecretType { 18 | AKV_SECRET_URI, SECRET_VALUE 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /jmeter-java-dsl-azure/src/main/java/us/abstracta/jmeter/javadsl/azure/api/Subscription.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.azure.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | public class Subscription { 7 | 8 | private final String subscriptionId; 9 | private final String tenantId; 10 | 11 | @JsonCreator 12 | public Subscription(@JsonProperty("subscriptionId") String id, 13 | @JsonProperty("tenantId") String tenantId) { 14 | this.subscriptionId = id; 15 | this.tenantId = tenantId; 16 | } 17 | 18 | public String getId() { 19 | return subscriptionId; 20 | } 21 | 22 | public String getUrl() { 23 | return String.format("https://portal.azure.com/#@%s/resource/subscriptions/%s", tenantId, 24 | subscriptionId); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /jmeter-java-dsl-azure/src/main/java/us/abstracta/jmeter/javadsl/azure/api/Token.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.azure.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | public class Token { 7 | 8 | private final String accessToken; 9 | 10 | @JsonCreator 11 | public Token(@JsonProperty("access_token") String accessToken) { 12 | this.accessToken = accessToken; 13 | } 14 | 15 | public String getAccessToken() { 16 | return accessToken; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /jmeter-java-dsl-azure/src/main/resources/us/abstracta/jmeter/javadsl/version.txt: -------------------------------------------------------------------------------- 1 | ${project.version} -------------------------------------------------------------------------------- /jmeter-java-dsl-azure/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /jmeter-java-dsl-azure/src/test/resources/users.csv: -------------------------------------------------------------------------------- 1 | USER 2 | test 3 | test2 4 | -------------------------------------------------------------------------------- /jmeter-java-dsl-base-remote-engine/src/main/java/us/abstracta/jmeter/javadsl/engines/RemoteEngineException.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.engines; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * Is thrown when there is some problem contacting a remote engine service. 7 | * 8 | * @since 1.10 9 | */ 10 | public class RemoteEngineException extends IOException { 11 | 12 | private final int code; 13 | private final String body; 14 | 15 | public RemoteEngineException(int code, String errorResponse) { 16 | super("Error response obtained remote engine: " + errorResponse); 17 | this.code = code; 18 | this.body = errorResponse; 19 | } 20 | 21 | /** 22 | * @return the status code contained in remote engine API response. 23 | */ 24 | public int code() { 25 | return code; 26 | } 27 | 28 | /** 29 | * @return message body contained in remote engine API response. 30 | */ 31 | public String body() { 32 | return body; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /jmeter-java-dsl-blazemeter/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | us.abstracta.jmeter 9 | jmeter-java-dsl-parent 10 | 2.3-SNAPSHOT 11 | ../pom.xml 12 | 13 | jmeter-java-dsl-blazemeter 14 | 15 | ${project.artifactId} 16 | Module which allows to easily run jmeter-java-dsl test plans at scale in 17 | BlazeMeter. 18 | 19 | 20 | 21 | 22 | us.abstracta.jmeter 23 | jmeter-java-dsl-base-remote-engine 24 | ${project.version} 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /jmeter-java-dsl-blazemeter/src/main/java/us/abstracta/jmeter/javadsl/blazemeter/BlazeMeterException.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.blazemeter; 2 | 3 | import us.abstracta.jmeter.javadsl.engines.RemoteEngineException; 4 | 5 | /** 6 | * Exception thrown when getting an unsuccessful response from BlazeMeter API. 7 | * 8 | * @since 0.2 9 | */ 10 | // This class has been left to avoid breaking api compatibility 11 | public class BlazeMeterException extends RemoteEngineException { 12 | 13 | public BlazeMeterException(int code, String errorResponse) { 14 | super(code, errorResponse); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /jmeter-java-dsl-blazemeter/src/main/java/us/abstracta/jmeter/javadsl/blazemeter/api/ApiResponse.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.blazemeter.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | public class ApiResponse { 7 | 8 | private final T result; 9 | 10 | @JsonCreator 11 | private ApiResponse(@JsonProperty("result") T result) { 12 | this.result = result; 13 | } 14 | 15 | public T getResult() { 16 | return result; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /jmeter-java-dsl-blazemeter/src/main/java/us/abstracta/jmeter/javadsl/blazemeter/api/Location.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.blazemeter.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | public class Location { 7 | 8 | private final String id; 9 | private final String name; 10 | 11 | @JsonCreator 12 | public Location(@JsonProperty("id") String id, @JsonProperty("name") String name) { 13 | this.id = id; 14 | this.name = name; 15 | } 16 | 17 | public String getId() { 18 | return id; 19 | } 20 | 21 | public String getName() { 22 | return name; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /jmeter-java-dsl-blazemeter/src/main/java/us/abstracta/jmeter/javadsl/blazemeter/api/Project.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.blazemeter.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | public class Project { 7 | 8 | private final long id; 9 | private final long workspaceId; 10 | private long accountId; 11 | private String url; 12 | 13 | @JsonCreator 14 | public Project(@JsonProperty("id") long id, @JsonProperty("workspaceId") long workspaceId, 15 | @JsonProperty("accountId") Long accountId) { 16 | this.id = id; 17 | this.workspaceId = workspaceId; 18 | if (accountId != null) { 19 | this.accountId = accountId; 20 | } 21 | } 22 | 23 | public void setBaseUrl(String baseUrl) { 24 | url = baseUrl + String 25 | .format("/accounts/%d/workspaces/%d/projects/%d", accountId, workspaceId, id); 26 | } 27 | 28 | public long getId() { 29 | return id; 30 | } 31 | 32 | public long getAccountId() { 33 | return accountId; 34 | } 35 | 36 | public void setAccountId(long accountId) { 37 | this.accountId = accountId; 38 | } 39 | 40 | public long getWorkspaceId() { 41 | return workspaceId; 42 | } 43 | 44 | public String getUrl() { 45 | return url; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /jmeter-java-dsl-blazemeter/src/main/java/us/abstracta/jmeter/javadsl/blazemeter/api/Test.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.blazemeter.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | public class Test { 7 | 8 | private final long id; 9 | private Project project; 10 | private String url; 11 | 12 | @JsonCreator 13 | private Test(@JsonProperty("id") long id) { 14 | this.id = id; 15 | } 16 | 17 | public void setProject(Project project) { 18 | this.project = project; 19 | this.url = project.getUrl() + "/tests/" + id; 20 | } 21 | 22 | public long getId() { 23 | return id; 24 | } 25 | 26 | public Project getProject() { 27 | return project; 28 | } 29 | 30 | public String getUrl() { 31 | return url; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /jmeter-java-dsl-blazemeter/src/main/java/us/abstracta/jmeter/javadsl/blazemeter/api/TestFile.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.blazemeter.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | public class TestFile { 7 | 8 | private final String name; 9 | 10 | @JsonCreator 11 | public TestFile(@JsonProperty("name") String name) { 12 | this.name = name; 13 | } 14 | 15 | public String getName() { 16 | return name; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /jmeter-java-dsl-blazemeter/src/main/java/us/abstracta/jmeter/javadsl/blazemeter/api/TestFileDeleteRequest.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.blazemeter.api; 2 | 3 | public class TestFileDeleteRequest { 4 | 5 | private final String fileName; 6 | 7 | public TestFileDeleteRequest(String fileName) { 8 | this.fileName = fileName; 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /jmeter-java-dsl-blazemeter/src/main/java/us/abstracta/jmeter/javadsl/blazemeter/api/TestRunConfig.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.blazemeter.api; 2 | 3 | public class TestRunConfig { 4 | 5 | private boolean isDebugRun; 6 | 7 | public TestRunConfig debugRun() { 8 | isDebugRun = true; 9 | return this; 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /jmeter-java-dsl-blazemeter/src/main/java/us/abstracta/jmeter/javadsl/blazemeter/api/TestRunStatus.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.blazemeter.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import java.util.Objects; 6 | 7 | public class TestRunStatus { 8 | 9 | public static final TestRunStatus CREATED = new TestRunStatus("CREATED", false); 10 | public static final TestRunStatus ENDED = new TestRunStatus("ENDED", false); 11 | 12 | private final String status; 13 | private final boolean isDataAvailable; 14 | 15 | @JsonCreator 16 | private TestRunStatus(@JsonProperty("status") String status, 17 | @JsonProperty("isDataAvailable") boolean isDataAvailable) { 18 | this.status = status; 19 | this.isDataAvailable = isDataAvailable; 20 | } 21 | 22 | public boolean isDataAvailable() { 23 | return isDataAvailable; 24 | } 25 | 26 | @Override 27 | public boolean equals(Object o) { 28 | if (this == o) { 29 | return true; 30 | } 31 | if (o == null || getClass() != o.getClass()) { 32 | return false; 33 | } 34 | TestRunStatus that = (TestRunStatus) o; 35 | return Objects.equals(status, that.status); 36 | } 37 | 38 | @Override 39 | public int hashCode() { 40 | return Objects.hash(status); 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return status; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /jmeter-java-dsl-blazemeter/src/main/java/us/abstracta/jmeter/javadsl/blazemeter/api/TestRunSummaryStats.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.blazemeter.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import java.time.Instant; 6 | import java.util.List; 7 | 8 | public class TestRunSummaryStats { 9 | 10 | private final List summary; 11 | 12 | @JsonCreator 13 | private TestRunSummaryStats(@JsonProperty("summary") List summary) { 14 | this.summary = summary; 15 | } 16 | 17 | public static class TestRunLabeledSummary { 18 | 19 | private final Instant first; 20 | private final Instant last; 21 | 22 | @JsonCreator 23 | private TestRunLabeledSummary(@JsonProperty("first") Instant first, 24 | @JsonProperty("last") Instant last) { 25 | this.first = first; 26 | this.last = last; 27 | } 28 | 29 | public Instant getFirst() { 30 | return first; 31 | } 32 | 33 | public Instant getLast() { 34 | return last; 35 | } 36 | 37 | } 38 | 39 | public List getSummary() { 40 | return summary; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /jmeter-java-dsl-blazemeter/src/main/java/us/abstracta/jmeter/javadsl/blazemeter/api/User.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.blazemeter.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | public class User { 7 | 8 | private final Project defaultProject; 9 | 10 | @JsonCreator 11 | private User(@JsonProperty("defaultProject") Project defaultProject) { 12 | this.defaultProject = defaultProject; 13 | } 14 | 15 | public Project getDefaultProject() { 16 | return defaultProject; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /jmeter-java-dsl-blazemeter/src/main/java/us/abstracta/jmeter/javadsl/blazemeter/api/Workspace.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.blazemeter.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | public class Workspace { 7 | 8 | private final long accountId; 9 | 10 | @JsonCreator 11 | private Workspace(@JsonProperty("accountId") long accountId) { 12 | this.accountId = accountId; 13 | } 14 | 15 | public long getAccountId() { 16 | return accountId; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /jmeter-java-dsl-blazemeter/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /jmeter-java-dsl-blazemeter/src/test/resources/users.csv: -------------------------------------------------------------------------------- 1 | USER 2 | test 3 | test2 4 | -------------------------------------------------------------------------------- /jmeter-java-dsl-bridge/src/main/java/us/abstracta/jmeter/javadsl/bridge/TestPlanExecution.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.bridge; 2 | 3 | import us.abstracta.jmeter.javadsl.core.DslJmeterEngine; 4 | import us.abstracta.jmeter.javadsl.core.DslTestPlan; 5 | 6 | public class TestPlanExecution { 7 | 8 | private final DslJmeterEngine engine; 9 | private final DslTestPlan testPlan; 10 | 11 | public TestPlanExecution(DslJmeterEngine engine, DslTestPlan testPlan) { 12 | this.engine = engine; 13 | this.testPlan = testPlan; 14 | } 15 | 16 | public DslJmeterEngine getEngine() { 17 | return engine; 18 | } 19 | 20 | public DslTestPlan getTestPlan() { 21 | return testPlan; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /jmeter-java-dsl-bridge/src/main/java/us/abstracta/jmeter/javadsl/bridge/serialization/BridgedObjectDeserializer.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.bridge.serialization; 2 | 3 | import java.io.IOException; 4 | import java.io.Reader; 5 | import java.io.StringReader; 6 | import org.apache.commons.io.IOUtils; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.yaml.snakeyaml.Yaml; 10 | 11 | public class BridgedObjectDeserializer { 12 | 13 | private static final Logger LOG = LoggerFactory.getLogger(BridgedObjectDeserializer.class); 14 | 15 | private final Yaml yaml = new Yaml(new BridgedObjectConstructor()); 16 | 17 | public T deserialize(Reader reader) { 18 | try { 19 | if (LOG.isDebugEnabled()) { 20 | String in = IOUtils.toString(reader); 21 | LOG.debug("Loading {}", in); 22 | reader = new StringReader(in); 23 | } 24 | return yaml.load(reader); 25 | } catch (IOException e) { 26 | throw new RuntimeException(e); 27 | } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /jmeter-java-dsl-bridge/src/main/java/us/abstracta/jmeter/javadsl/bridge/serialization/BuilderMethod.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.bridge.serialization; 2 | 3 | import java.lang.reflect.Parameter; 4 | 5 | public interface BuilderMethod { 6 | 7 | Object invoke(Object... args) throws ReflectiveOperationException; 8 | 9 | Parameter[] getParameters(); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /jmeter-java-dsl-bridge/src/main/java/us/abstracta/jmeter/javadsl/bridge/serialization/TestElementConstructorException.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.bridge.serialization; 2 | 3 | import org.yaml.snakeyaml.constructor.ConstructorException; 4 | import org.yaml.snakeyaml.nodes.Node; 5 | 6 | public class TestElementConstructorException extends ConstructorException { 7 | 8 | public TestElementConstructorException(String elementTypeName, Node node, String problem) { 9 | super("while constructing a " + elementTypeName, node.getStartMark(), 10 | problem, node.getEndMark()); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /jmeter-java-dsl-bridge/src/main/java/us/abstracta/jmeter/javadsl/bridge/serialization/constructs/BaseBridgedObjectConstruct.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.bridge.serialization.constructs; 2 | 3 | import java.util.LinkedHashMap; 4 | import java.util.Map; 5 | import java.util.stream.Collectors; 6 | import org.yaml.snakeyaml.constructor.AbstractConstruct; 7 | import org.yaml.snakeyaml.nodes.MappingNode; 8 | import org.yaml.snakeyaml.nodes.Node; 9 | import org.yaml.snakeyaml.nodes.NodeTuple; 10 | import org.yaml.snakeyaml.nodes.ScalarNode; 11 | import us.abstracta.jmeter.javadsl.bridge.serialization.TestElementConstructorException; 12 | 13 | public abstract class BaseBridgedObjectConstruct extends AbstractConstruct { 14 | 15 | protected static Map getNodeProperties(Node node, String tag) { 16 | MappingNode mappingNode = castNode(node, MappingNode.class, "map", tag); 17 | return mappingNode.getValue().stream() 18 | .collect(Collectors.toMap(n -> ((ScalarNode) n.getKeyNode()).getValue(), 19 | NodeTuple::getValueNode, (u, v) -> u, LinkedHashMap::new)); 20 | } 21 | 22 | protected static T castNode(Node node, Class nodeType, String name, 23 | String tag) { 24 | if (!nodeType.isInstance(node)) { 25 | throw new TestElementConstructorException(tag, node, 26 | String.format("found a %s while expecting a %s", node.getClass(), name)); 27 | } 28 | return nodeType.cast(node); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /jmeter-java-dsl-bridge/src/main/java/us/abstracta/jmeter/javadsl/bridge/serialization/constructs/HttpHeadersConstruct.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.bridge.serialization.constructs; 2 | 3 | import java.util.Map; 4 | import org.yaml.snakeyaml.nodes.Node; 5 | import org.yaml.snakeyaml.nodes.ScalarNode; 6 | import us.abstracta.jmeter.javadsl.http.HttpHeaders; 7 | 8 | public class HttpHeadersConstruct extends BaseBridgedObjectConstruct { 9 | 10 | @Override 11 | public Object construct(Node node) { 12 | Map properties = getNodeProperties(node, "httpHeaders"); 13 | HttpHeaders ret = new HttpHeaders(); 14 | properties.forEach((key, value) -> ret.header(key, ((ScalarNode) value).getValue())); 15 | return ret; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /jmeter-java-dsl-bridge/src/main/java/us/abstracta/jmeter/javadsl/bridge/serialization/constructs/TestPlanExecutionConstruct.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.bridge.serialization.constructs; 2 | 3 | import java.util.Map; 4 | import org.yaml.snakeyaml.nodes.Node; 5 | import us.abstracta.jmeter.javadsl.bridge.TestPlanExecution; 6 | import us.abstracta.jmeter.javadsl.bridge.serialization.BridgedObjectConstructor; 7 | import us.abstracta.jmeter.javadsl.bridge.serialization.TestElementConstructorException; 8 | import us.abstracta.jmeter.javadsl.core.DslJmeterEngine; 9 | import us.abstracta.jmeter.javadsl.core.DslTestPlan; 10 | 11 | public class TestPlanExecutionConstruct extends BaseBridgedObjectConstruct { 12 | 13 | private static final String TAG = "testPlanExecution"; 14 | private final BridgedObjectConstructor constructor; 15 | 16 | public TestPlanExecutionConstruct(BridgedObjectConstructor constructor) { 17 | this.constructor = constructor; 18 | } 19 | 20 | @Override 21 | public Object construct(Node node) { 22 | Map properties = getNodeProperties(node, TAG); 23 | DslJmeterEngine engine = (DslJmeterEngine) constructor.constructObject( 24 | properties.remove("engine")); 25 | DslTestPlan testPlan = (DslTestPlan) constructor.constructObject( 26 | properties.remove("testPlan")); 27 | if (!properties.isEmpty()) { 28 | throw new TestElementConstructorException(TAG, node, 29 | "unknown properties " + String.join(",", properties.keySet())); 30 | } 31 | return new TestPlanExecution(engine, testPlan); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /jmeter-java-dsl-bridge/src/test/resources/simpleTestPlan-out.template.yml: -------------------------------------------------------------------------------- 1 | duration: PT{{\d+\.\d+}}S 2 | overall: 3 | firstTime: '{{[0-9:.TZ-]+}}' 4 | receivedBytes: 5 | total: {{\d+}} 6 | perSecond: {{\d+\.\d+}} 7 | endTime: '{{[0-9:.TZ-]+}}' 8 | sentBytes: 9 | total: {{\d+}} 10 | perSecond: {{\d+\.\d+}} 11 | samples: 12 | total: {{\d+}} 13 | perSecond: {{\d+\.\d+}} 14 | errors: 15 | total: {{\d+}} 16 | perSecond: {{\d+\.\d+}} 17 | sampleTime: 18 | perc95: PT{{\d+\.\d+}}S 19 | min: PT{{\d+\.\d+}}S 20 | median: PT{{\d+\.\d+}}S 21 | max: PT{{\d+\.\d+}}S 22 | perc99: PT{{\d+\.\d+}}S 23 | mean: PT{{\d+\.\d+}}S 24 | perc90: PT{{\d+\.\d+}}S 25 | labels: 26 | HTTP Request: 27 | firstTime: '{{[0-9:.TZ-]+}}' 28 | receivedBytes: 29 | total: {{\d+}} 30 | perSecond: {{\d+\.\d+}} 31 | endTime: '{{[0-9:.TZ-]+}}' 32 | sentBytes: 33 | total: {{\d+}} 34 | perSecond: {{\d+\.\d+}} 35 | samples: 36 | total: {{\d+}} 37 | perSecond: {{\d+\.\d+}} 38 | errors: 39 | total: {{\d+}} 40 | perSecond: {{\d+\.\d+}} 41 | sampleTime: 42 | perc95: PT{{\d+\.\d+}}S 43 | min: PT{{\d+\.\d+}}S 44 | median: PT{{\d+\.\d+}}S 45 | max: PT{{\d+\.\d+}}S 46 | perc99: PT{{\d+\.\d+}}S 47 | mean: PT{{\d+\.\d+}}S 48 | perc90: PT{{\d+\.\d+}}S 49 | -------------------------------------------------------------------------------- /jmeter-java-dsl-bridge/src/test/resources/simpleTestPlan.yml: -------------------------------------------------------------------------------- 1 | !testPlanExecution 2 | engine: !embeddedJmeterEngine {} 3 | testPlan: 4 | !testPlan 5 | children: 6 | - !threadGroup 7 | threads: 1 8 | iterations: 1 9 | children: 10 | - !httpSampler 11 | method: POST 12 | url: "http://localhost" 13 | body: '{"prop": "val"}' 14 | children: 15 | !httpHeaders 16 | Content-Type: application/json 17 | -------------------------------------------------------------------------------- /jmeter-java-dsl-cli/src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /jmeter-java-dsl-cli/src/test/resources/TestPlan.java: -------------------------------------------------------------------------------- 1 | testPlan( 2 | threadGroup(1, 3, 3 | httpSampler("http://localhost") 4 | .post("{\"var\":\"val\"}", ContentType.APPLICATION_JSON), 5 | httpSampler("http://localhost") 6 | ) 7 | ) -------------------------------------------------------------------------------- /jmeter-java-dsl-cli/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /jmeter-java-dsl-dashboard/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /jmeter-java-dsl-datadog/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /jmeter-java-dsl-elasticsearch-listener/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /jmeter-java-dsl-graphql/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | jmeter-java-dsl-parent 8 | us.abstracta.jmeter 9 | 2.3-SNAPSHOT 10 | ../pom.xml 11 | 12 | 13 | jmeter-java-dsl-graphql 14 | ${project.artifactId} 15 | Module which includes test elements to simplify generating GraphQL requests. 16 | 17 | 18 | 19 | 20 | us.abstracta.jmeter 21 | jmeter-java-dsl 22 | ${project.version} 23 | 24 | 25 | com.fasterxml.jackson.core 26 | jackson-databind 27 | 28 | 29 | com.fasterxml.jackson.core 30 | jackson-core 31 | 32 | 33 | us.abstracta.jmeter 34 | jmeter-java-dsl 35 | test-jar 36 | ${project.version} 37 | test 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /jmeter-java-dsl-jdbc/src/test/java/us/abstracta/jmeter/javadsl/jdbc/DslJdbcConnectionPoolTest.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.jdbc; 2 | 3 | import static us.abstracta.jmeter.javadsl.JmeterDsl.testPlan; 4 | import static us.abstracta.jmeter.javadsl.jdbc.JdbcJmeterDsl.jdbcConnectionPool; 5 | 6 | import java.sql.Connection; 7 | import java.time.Duration; 8 | import org.junit.jupiter.api.Nested; 9 | import org.postgresql.Driver; 10 | import us.abstracta.jmeter.javadsl.codegeneration.MethodCallBuilderTest; 11 | import us.abstracta.jmeter.javadsl.core.DslTestPlan; 12 | 13 | public class DslJdbcConnectionPoolTest { 14 | 15 | @Nested 16 | public class CodeBuilderTest extends MethodCallBuilderTest { 17 | 18 | protected CodeBuilderTest() { 19 | codeGenerator.addBuildersFrom(JdbcJmeterDsl.class); 20 | } 21 | 22 | public DslTestPlan testPlanWithConnectionPool() { 23 | return testPlan( 24 | jdbcConnectionPool("myPool", Driver.class, "jdbc:postgresql://localhost/my_db") 25 | ); 26 | } 27 | 28 | public DslTestPlan testPlanWithConnectionPoolAndNonDefaultSettngs() { 29 | return testPlan( 30 | jdbcConnectionPool("myPool", Driver.class, "jdbc:postgresql://localhost/my_db") 31 | .user("myUser") 32 | .password("myPassword") 33 | .autoCommit(false) 34 | .maxConnections(10) 35 | .maxConnectionWait(Duration.ofSeconds(5)) 36 | .transactionIsolation(Connection.TRANSACTION_NONE) 37 | ); 38 | } 39 | 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /jmeter-java-dsl-jdbc/src/test/resources/init.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE users( 2 | id SERIAL, 3 | name VARCHAR(255), 4 | age INT, 5 | address VARCHAR(500) 6 | ); 7 | 8 | INSERT INTO users(name, age, address) VALUES 9 | ('User1', 21, 'My address1'), 10 | ('User2', 22, 'My address2'); 11 | 12 | CREATE OR REPLACE FUNCTION incr(INOUT num INT) 13 | RETURNS INT AS ' 14 | BEGIN 15 | num := num + 1; 16 | END; 17 | ' 18 | LANGUAGE plpgsql; 19 | -------------------------------------------------------------------------------- /jmeter-java-dsl-octoperf/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | 7 | us.abstracta.jmeter 8 | jmeter-java-dsl-parent 9 | 2.3-SNAPSHOT 10 | ../pom.xml 11 | 12 | jmeter-java-dsl-octoperf 13 | 14 | ${project.artifactId} 15 | Module which allows to easily run jmeter-java-dsl test plans at scale in OctoPerf. 16 | 17 | 18 | 19 | 20 | us.abstracta.jmeter 21 | jmeter-java-dsl-base-remote-engine 22 | ${project.version} 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /jmeter-java-dsl-octoperf/src/main/java/us/abstracta/jmeter/javadsl/octoperf/OctoPerfException.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.octoperf; 2 | 3 | import us.abstracta.jmeter.javadsl.engines.RemoteEngineException; 4 | 5 | /** 6 | * Exception thrown when getting an unsuccessful response from OctoPerf API. 7 | * 8 | * @since 0.58 9 | */ 10 | // This class has been left to avoid breaking api compatibility 11 | public class OctoPerfException extends RemoteEngineException { 12 | 13 | public OctoPerfException(int code, String errorResponse) { 14 | super(code, errorResponse); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /jmeter-java-dsl-octoperf/src/main/java/us/abstracta/jmeter/javadsl/octoperf/api/BenchResult.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.octoperf.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import java.time.Instant; 6 | 7 | public class BenchResult { 8 | 9 | private final State state; 10 | private final Instant created; 11 | private final Instant lastModified; 12 | 13 | @JsonCreator 14 | public BenchResult(@JsonProperty("state") State state, @JsonProperty("created") Instant created, 15 | @JsonProperty("lastModified") Instant lastModified) { 16 | this.state = state; 17 | this.created = created; 18 | this.lastModified = lastModified; 19 | } 20 | 21 | public State getState() { 22 | return state; 23 | } 24 | 25 | public Instant getCreated() { 26 | return created; 27 | } 28 | 29 | public Instant getLastModified() { 30 | return lastModified; 31 | } 32 | 33 | public enum State { 34 | CREATED, PENDING, SCALING, PREPARING, INITIALIZING, RUNNING, FINISHED, ABORTED, ERROR; 35 | 36 | public boolean isFinalState() { 37 | return this == FINISHED || this == ABORTED || this == ERROR; 38 | } 39 | 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /jmeter-java-dsl-octoperf/src/main/java/us/abstracta/jmeter/javadsl/octoperf/api/Provider.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.octoperf.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import java.util.Map; 6 | 7 | public class Provider { 8 | 9 | private final String id; 10 | private final Map regions; 11 | 12 | @JsonCreator 13 | public Provider(@JsonProperty("id") String id, 14 | @JsonProperty("regions") Map regions) { 15 | this.id = id; 16 | this.regions = regions; 17 | } 18 | 19 | public String getId() { 20 | return id; 21 | } 22 | 23 | public Map getRegions() { 24 | return regions; 25 | } 26 | 27 | public static class Region { 28 | 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /jmeter-java-dsl-octoperf/src/main/java/us/abstracta/jmeter/javadsl/octoperf/api/TableEntry.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.octoperf.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import java.util.List; 6 | 7 | public class TableEntry { 8 | 9 | private final String actionId; 10 | private final List values; 11 | 12 | @JsonCreator 13 | public TableEntry(@JsonProperty("actionId") String actionId, 14 | @JsonProperty("values") List values) { 15 | this.actionId = actionId; 16 | this.values = values; 17 | } 18 | 19 | public String getActionId() { 20 | return actionId; 21 | } 22 | 23 | public List getValues() { 24 | return values; 25 | } 26 | 27 | public static class TableValue { 28 | 29 | private final double value; 30 | 31 | @JsonCreator 32 | public TableValue(@JsonProperty("value") double value) { 33 | this.value = value; 34 | } 35 | 36 | public double getValue() { 37 | return value; 38 | } 39 | 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /jmeter-java-dsl-octoperf/src/main/java/us/abstracta/jmeter/javadsl/octoperf/api/User.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.octoperf.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | public class User { 7 | 8 | private final String id; 9 | 10 | @JsonCreator 11 | private User(@JsonProperty("id") String id) { 12 | this.id = id; 13 | } 14 | 15 | public String getId() { 16 | return id; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /jmeter-java-dsl-octoperf/src/main/java/us/abstracta/jmeter/javadsl/octoperf/api/Workspace.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.octoperf.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | public class Workspace { 7 | 8 | private final String id; 9 | private String baseUrl; 10 | 11 | @JsonCreator 12 | private Workspace(@JsonProperty("id") String id) { 13 | this.id = id; 14 | } 15 | 16 | public String getId() { 17 | return id; 18 | } 19 | 20 | public void setBaseAppUrl(String baseAppUrl) { 21 | baseUrl = baseAppUrl + "/workspace/" + id; 22 | } 23 | 24 | public String getBaseUrl() { 25 | return baseUrl; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /jmeter-java-dsl-octoperf/src/test/java/us/abstracta/jmeter/javadsl/octoperf/OctoPerfEngineTest.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.octoperf; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | import static us.abstracta.jmeter.javadsl.JmeterDsl.httpSampler; 5 | import static us.abstracta.jmeter.javadsl.JmeterDsl.testPlan; 6 | import static us.abstracta.jmeter.javadsl.JmeterDsl.threadGroup; 7 | 8 | import java.time.Duration; 9 | import org.junit.jupiter.api.Test; 10 | import us.abstracta.jmeter.javadsl.core.TestPlanStats; 11 | 12 | public class OctoPerfEngineTest { 13 | 14 | @Test 15 | public void shouldRunTestInOctoPerf() throws Exception { 16 | TestPlanStats stats = testPlan( 17 | threadGroup(1, 1, 18 | httpSampler("https://localhost") 19 | ) 20 | ).runIn(new OctoPerfEngine(System.getenv("OCTOPERF_API_KEY")) 21 | .projectName("jmeter-java-dsl") 22 | .totalUsers(1) 23 | .holdFor(Duration.ofSeconds(10)) 24 | .testTimeout(Duration.ofMinutes(10))); 25 | assertThat(stats.overall().samplesCount()).isGreaterThanOrEqualTo(1); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /jmeter-java-dsl-octoperf/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /jmeter-java-dsl-parallel/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /jmeter-java-dsl-prometheus/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | us.abstracta.jmeter 8 | jmeter-java-dsl-parent 9 | 2.3-SNAPSHOT 10 | ../pom.xml 11 | 12 | jmeter-java-dsl-prometheus 13 | ${project.artifactId} 14 | Module which includes Prometheus listener plugin for exposing JMeter metrics. 15 | 16 | 17 | 18 | jitpack.io 19 | https://jitpack.io 20 | 21 | 22 | 23 | 24 | 25 | us.abstracta.jmeter 26 | jmeter-java-dsl 27 | ${project.version} 28 | 29 | 30 | com.github.johrstrom 31 | jmeter-prometheus-plugin 32 | 0.7.1 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /jmeter-java-dsl-recorder/src/main/java/us/abstracta/jmeter/javadsl/recorder/correlations/CorrelationRuleBuilder.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.recorder.correlations; 2 | 3 | import com.blazemeter.jmeter.correlation.core.CorrelationRule; 4 | import com.fasterxml.jackson.annotation.JsonCreator; 5 | import com.fasterxml.jackson.annotation.JsonProperty; 6 | import java.util.regex.Pattern; 7 | 8 | public class CorrelationRuleBuilder { 9 | 10 | private final String variableName; 11 | private final CorrelationExtractorBuilder extractor; 12 | private final CorrelationReplacementBuilder replacement; 13 | 14 | public CorrelationRuleBuilder(String variableName, Pattern extractorRegex, 15 | Pattern replacementRegex) { 16 | this(variableName, 17 | extractorRegex != null ? new CorrelationExtractorBuilder(extractorRegex) : null, 18 | replacementRegex != null ? new CorrelationReplacementBuilder(replacementRegex) : null); 19 | } 20 | 21 | @JsonCreator 22 | public CorrelationRuleBuilder(@JsonProperty("variable") String variableName, 23 | @JsonProperty("extractor") CorrelationExtractorBuilder extractor, 24 | @JsonProperty("replacement") CorrelationReplacementBuilder replacement) { 25 | this.variableName = variableName; 26 | this.extractor = extractor; 27 | this.replacement = replacement; 28 | } 29 | 30 | public CorrelationRule build() { 31 | return new CorrelationRule(variableName, extractor != null ? extractor.build() : null, 32 | replacement != null ? replacement.build() : null); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /jmeter-java-dsl-recorder/src/main/resources/us/abstracta/jmeter/javadsl/version.txt: -------------------------------------------------------------------------------- 1 | ${project.version} -------------------------------------------------------------------------------- /jmeter-java-dsl-recorder/src/test/java/us/abstracta/jmeter/javadsl/recorder/RetailStoreMock.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.recorder; 2 | 3 | import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; 4 | 5 | import com.github.tomakehurst.wiremock.WireMockServer; 6 | import com.github.tomakehurst.wiremock.extension.responsetemplating.ResponseTemplateTransformer; 7 | import java.net.MalformedURLException; 8 | import java.net.URL; 9 | 10 | public class RetailStoreMock implements AutoCloseable { 11 | 12 | private final WireMockServer server; 13 | 14 | public RetailStoreMock(int port) { 15 | server = new WireMockServer(wireMockConfig() 16 | .withRootDirectory("src/test/resources/retailstore-mock") 17 | .extensions(new ResponseTemplateTransformer(false)) 18 | .port(port)); 19 | server.start(); 20 | } 21 | 22 | public URL getUrl() { 23 | try { 24 | return new URL(server.baseUrl()); 25 | } catch (MalformedURLException e) { 26 | throw new RuntimeException(e); 27 | } 28 | } 29 | 30 | @Override 31 | public void close() throws Exception { 32 | server.stop(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /jmeter-java-dsl-recorder/src/test/resources/RecordedTestPlan.template.java: -------------------------------------------------------------------------------- 1 | testPlan( 2 | threadGroup(1, 1, 3 | httpDefaults() 4 | .encoding(StandardCharsets.UTF_8) 5 | .followRedirects(false) 6 | .useKeepAlive(false), 7 | httpSampler("/-{{\d+}}", "http://localhost:{{\d+}}"), 8 | httpSampler("/home-{{\d+}}", "http://localhost:{{\d+}}/home") 9 | .children( 10 | regexExtractor("productId#2", "name=\"productId\" value=\"([^\"]+)\"") 11 | .defaultValue("productId#2_NOT_FOUND") 12 | ), 13 | httpSampler("/cart-{{\d+}}", "http://localhost:{{\d+}}/cart") 14 | .method(HTTPConstants.POST) 15 | .contentType(ContentType.APPLICATION_FORM_URLENCODED) 16 | .param("productId", "${productId#2}"), 17 | httpSampler("/cart-{{\d+}}", "http://localhost:{{\d+}}/cart") 18 | .children( 19 | regexExtractor("productId#4", "name=\"productId\" value=\"([^\"]+)\"") 20 | .defaultValue("productId#4_NOT_FOUND") 21 | ) 22 | ) 23 | ) -------------------------------------------------------------------------------- /jmeter-java-dsl-recorder/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /jmeter-java-dsl-recorder/src/test/resources/retailstore-mock/__files/assets/chrono_classic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/jmeter-java-dsl-recorder/src/test/resources/retailstore-mock/__files/assets/chrono_classic.jpg -------------------------------------------------------------------------------- /jmeter-java-dsl-recorder/src/test/resources/retailstore-mock/__files/assets/gentleman.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/jmeter-java-dsl-recorder/src/test/resources/retailstore-mock/__files/assets/gentleman.jpg -------------------------------------------------------------------------------- /jmeter-java-dsl-recorder/src/test/resources/retailstore-mock/__files/assets/pocket_watch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/jmeter-java-dsl-recorder/src/test/resources/retailstore-mock/__files/assets/pocket_watch.jpg -------------------------------------------------------------------------------- /jmeter-java-dsl-recorder/src/test/resources/retailstore-mock/__files/assets/wood_watch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/jmeter-java-dsl-recorder/src/test/resources/retailstore-mock/__files/assets/wood_watch.jpg -------------------------------------------------------------------------------- /jmeter-java-dsl-recorder/src/test/resources/retailstore-mock/__files/webjars/bootstrap-icons/font/fonts/bootstrap-icons.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/jmeter-java-dsl-recorder/src/test/resources/retailstore-mock/__files/webjars/bootstrap-icons/font/fonts/bootstrap-icons.woff2 -------------------------------------------------------------------------------- /jmeter-java-dsl-recorder/src/test/resources/retailstore-mock/mappings/mappings.json: -------------------------------------------------------------------------------- 1 | { 2 | "mappings": [ 3 | { 4 | "request": { 5 | "url": "/", 6 | "method": "GET" 7 | }, 8 | "response": { 9 | "status": 303, 10 | "headers": { 11 | "Location": "/home", 12 | "Set-Cookie": "SESSIONID=7b2c2f9a-0aca-4322-951b-4832863a0b04" 13 | } 14 | } 15 | }, 16 | { 17 | "request": { 18 | "url": "/cart", 19 | "method": "POST", 20 | "bodyPatterns": [ 21 | { 22 | "equalTo": "productId=510a0d7e-8e83-4193-b483-e27e09ddc34d", 23 | "caseInsensitive": false 24 | } 25 | ] 26 | }, 27 | "response": { 28 | "status": 303, 29 | "headers": { 30 | "Location": "/cart" 31 | } 32 | } 33 | }, 34 | { 35 | "priority": 10, 36 | "request": { 37 | "urlPattern": "/[^\\./]+", 38 | "method": "GET" 39 | }, 40 | "response": { 41 | "status": 200, 42 | "bodyFileName": "{{substring request.path 1}}.html", 43 | "headers": { 44 | "Content-Type": "text/html", 45 | "Content-Language": "es-ES", 46 | "X-Content-Encoding-Over-Network": "gzip" 47 | }, 48 | "transformers": ["response-template"] 49 | } 50 | } 51 | ] 52 | } -------------------------------------------------------------------------------- /jmeter-java-dsl-websocket/src/test/java/WebSocketEchoServer.java: -------------------------------------------------------------------------------- 1 | import java.net.InetSocketAddress; 2 | import java.util.concurrent.CountDownLatch; 3 | import java.util.concurrent.TimeUnit; 4 | import org.java_websocket.WebSocket; 5 | import org.java_websocket.handshake.ClientHandshake; 6 | import org.java_websocket.server.WebSocketServer; 7 | 8 | public class WebSocketEchoServer extends WebSocketServer { 9 | 10 | private final CountDownLatch startLatch = new CountDownLatch(1); 11 | 12 | public WebSocketEchoServer(int port) { 13 | super(new InetSocketAddress(port)); 14 | } 15 | 16 | @Override 17 | public void onOpen(WebSocket conn, ClientHandshake handshake) { 18 | } 19 | 20 | @Override 21 | public void onClose(WebSocket conn, int code, String reason, boolean remote) { 22 | } 23 | 24 | @Override 25 | public void onMessage(WebSocket conn, String message) { 26 | conn.send(message); 27 | } 28 | 29 | @Override 30 | public void onError(WebSocket conn, Exception ex) { 31 | ex.printStackTrace(); 32 | } 33 | 34 | @Override 35 | public void onStart() { 36 | startLatch.countDown(); 37 | } 38 | 39 | public void awaitStart(long timeout, TimeUnit unit) throws InterruptedException { 40 | if (!startLatch.await(timeout, unit)) { 41 | throw new RuntimeException("WebSocket server failed to start within timeout"); 42 | } 43 | } 44 | 45 | public String getUri() { 46 | return "ws://localhost:" + getPort(); 47 | } 48 | } -------------------------------------------------------------------------------- /jmeter-java-dsl-websocket/src/test/resources/websocket-codegeneration/ComplexWebSocketTest.java: -------------------------------------------------------------------------------- 1 | testPlan( 2 | threadGroup(1, 1, 3 | websocketConnect("ws://echo.websocket.org:80/") 4 | .connectionTimeout(15000) 5 | .responseTimeout(10000), 6 | websocketWrite("Hello from JMeter WebSocket Test"), 7 | websocketRead() 8 | .responseTimeout(10000) 9 | .waitForResponse(false), 10 | websocketDisconnect() 11 | .responseTimeout(2000) 12 | .statusCode("3000") 13 | ) 14 | ) -------------------------------------------------------------------------------- /jmeter-java-dsl-websocket/src/test/resources/websocket-codegeneration/SimpleWebSocketTest.java: -------------------------------------------------------------------------------- 1 | testPlan( 2 | threadGroup(1, 1, 3 | websocketConnect("ws://ws.postman-echo.com:80/raw"), 4 | websocketWrite("Hello WebSocket Test!"), 5 | websocketRead(), 6 | websocketDisconnect() 7 | ) 8 | ) -------------------------------------------------------------------------------- /jmeter-java-dsl-websocket/src/test/resources/websocket-codegeneration/WebSocketWithVariablesTest.java: -------------------------------------------------------------------------------- 1 | testPlan( 2 | threadGroup(1, 1, 3 | websocketConnect("ws://${WEBSOCKET_SERVER}:${WEBSOCKET_PORT}/raw") 4 | .connectionTimeout("${timeout}") 5 | .responseTimeout("${timeout}"), 6 | websocketWrite("${MESSAGE}"), 7 | websocketRead() 8 | .responseTimeout("${timeout}"), 9 | websocketDisconnect() 10 | .responseTimeout("${timeout}") 11 | .statusCode("${statusCode}") 12 | ) 13 | ) -------------------------------------------------------------------------------- /jmeter-java-dsl-wrapper/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | jmeter-java-dsl-parent 8 | us.abstracta.jmeter 9 | 2.3-SNAPSHOT 10 | ../pom.xml 11 | 12 | jmeter-java-dsl-wrapper 13 | 14 | ${project.artifactId} 15 | Module which includes wrapper elements for easy usage of custom or still not 16 | supported JMeter components. 17 | 18 | 19 | 20 | 21 | us.abstracta.jmeter 22 | jmeter-java-dsl 23 | ${project.version} 24 | 25 | 26 | us.abstracta.jmeter 27 | jmeter-java-dsl 28 | test-jar 29 | ${project.version} 30 | test 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /jmeter-java-dsl-wrapper/src/main/java/us/abstracta/jmeter/javadsl/wrapper/wrappers/TestElementWrapper.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.wrapper.wrappers; 2 | 3 | import us.abstracta.jmeter.javadsl.core.DslTestElement; 4 | 5 | /** 6 | * Is a test element which allows easy usage in DSL of custom or not supported JMeter test 7 | * elements. 8 | * 9 | * @param Is the type of the test element wrapper for usage in fluent API style. 10 | * @since 0.41 11 | */ 12 | public interface TestElementWrapper extends DslTestElement { 13 | 14 | /** 15 | * Allows specifying a property to be set on wrapped test element. 16 | * 17 | * @param name is the name of the property to be set. 18 | * @param value is the value to be associated to the property. 19 | * @return the test element wrapper for further configuration and usage. 20 | */ 21 | T prop(String name, Object value); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /jmeter-java-dsl-wrapper/src/test/java/us/abstracta/jmeter/javadsl/wrapper/customelements/MyAssertion.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.wrapper.customelements; 2 | 3 | import org.apache.jmeter.assertions.Assertion; 4 | import org.apache.jmeter.assertions.AssertionResult; 5 | import org.apache.jmeter.samplers.SampleResult; 6 | import org.apache.jmeter.testelement.AbstractTestElement; 7 | 8 | public class MyAssertion extends AbstractTestElement implements Assertion { 9 | 10 | @Override 11 | public AssertionResult getResult(SampleResult response) { 12 | return new AssertionResult("MyAssertion"); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /jmeter-java-dsl-wrapper/src/test/java/us/abstracta/jmeter/javadsl/wrapper/customelements/MyAssertionGui.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.wrapper.customelements; 2 | 3 | import org.apache.jmeter.assertions.gui.AbstractAssertionGui; 4 | import org.apache.jmeter.testelement.TestElement; 5 | 6 | public class MyAssertionGui extends AbstractAssertionGui { 7 | 8 | @Override 9 | public String getLabelResource() { 10 | return null; 11 | } 12 | 13 | @Override 14 | public TestElement createTestElement() { 15 | MyAssertion ret = new MyAssertion(); 16 | modifyTestElement(ret); 17 | return ret; 18 | } 19 | 20 | @Override 21 | public void modifyTestElement(TestElement element) { 22 | configureTestElement(element); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /jmeter-java-dsl-wrapper/src/test/java/us/abstracta/jmeter/javadsl/wrapper/customelements/MyAssertionTestBean.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.wrapper.customelements; 2 | 3 | import org.apache.jmeter.testbeans.TestBean; 4 | 5 | public class MyAssertionTestBean extends MyAssertion implements TestBean { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /jmeter-java-dsl-wrapper/src/test/java/us/abstracta/jmeter/javadsl/wrapper/customelements/MyController.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.wrapper.customelements; 2 | 3 | import org.apache.jmeter.control.GenericController; 4 | 5 | public class MyController extends GenericController { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /jmeter-java-dsl-wrapper/src/test/java/us/abstracta/jmeter/javadsl/wrapper/customelements/MyControllerGui.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.wrapper.customelements; 2 | 3 | import org.apache.jmeter.control.gui.AbstractControllerGui; 4 | import org.apache.jmeter.testelement.TestElement; 5 | 6 | public class MyControllerGui extends AbstractControllerGui { 7 | 8 | @Override 9 | public String getLabelResource() { 10 | return null; 11 | } 12 | 13 | @Override 14 | public TestElement createTestElement() { 15 | MyController ret = new MyController(); 16 | modifyTestElement(ret); 17 | return ret; 18 | } 19 | 20 | @Override 21 | public void modifyTestElement(TestElement element) { 22 | configureTestElement(element); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /jmeter-java-dsl-wrapper/src/test/java/us/abstracta/jmeter/javadsl/wrapper/customelements/MyControllerTestBean.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.wrapper.customelements; 2 | 3 | import org.apache.jmeter.testbeans.TestBean; 4 | 5 | public class MyControllerTestBean extends MyController implements TestBean { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /jmeter-java-dsl-wrapper/src/test/java/us/abstracta/jmeter/javadsl/wrapper/customelements/MySampler.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.wrapper.customelements; 2 | 3 | import org.apache.jmeter.samplers.AbstractSampler; 4 | import org.apache.jmeter.samplers.Entry; 5 | import org.apache.jmeter.samplers.SampleResult; 6 | 7 | public class MySampler extends AbstractSampler { 8 | 9 | @Override 10 | public SampleResult sample(Entry e) { 11 | return null; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /jmeter-java-dsl-wrapper/src/test/java/us/abstracta/jmeter/javadsl/wrapper/customelements/MySamplerGui.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.wrapper.customelements; 2 | 3 | import org.apache.jmeter.samplers.gui.AbstractSamplerGui; 4 | import org.apache.jmeter.testelement.TestElement; 5 | 6 | public class MySamplerGui extends AbstractSamplerGui { 7 | 8 | @Override 9 | public String getLabelResource() { 10 | return null; 11 | } 12 | 13 | @Override 14 | public TestElement createTestElement() { 15 | MySampler ret = new MySampler(); 16 | modifyTestElement(ret); 17 | return ret; 18 | } 19 | 20 | @Override 21 | public void modifyTestElement(TestElement element) { 22 | configureTestElement(element); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /jmeter-java-dsl-wrapper/src/test/java/us/abstracta/jmeter/javadsl/wrapper/customelements/MySamplerTestBean.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.wrapper.customelements; 2 | 3 | import org.apache.jmeter.testbeans.TestBean; 4 | 5 | public class MySamplerTestBean extends MySampler implements TestBean { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /jmeter-java-dsl-wrapper/src/test/java/us/abstracta/jmeter/javadsl/wrapper/customelements/MyThreadGroup.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.wrapper.customelements; 2 | 3 | import org.apache.jmeter.control.LoopController; 4 | import org.apache.jmeter.engine.StandardJMeterEngine; 5 | import org.apache.jmeter.testelement.TestElement; 6 | import org.apache.jmeter.threads.AbstractThreadGroup; 7 | import org.apache.jmeter.threads.JMeterThread; 8 | import org.apache.jmeter.threads.ListenerNotifier; 9 | import org.apache.jorphan.collections.ListedHashTree; 10 | 11 | public class MyThreadGroup extends AbstractThreadGroup { 12 | 13 | @Override 14 | public boolean stopThread(String threadName, boolean now) { 15 | return true; 16 | } 17 | 18 | @Override 19 | public int numberOfActiveThreads() { 20 | return 0; 21 | } 22 | 23 | @Override 24 | public void start(int groupCount, ListenerNotifier notifier, 25 | ListedHashTree threadGroupTree, StandardJMeterEngine engine) { 26 | } 27 | 28 | @Override 29 | public JMeterThread addNewThread(int delay, StandardJMeterEngine engine) { 30 | return null; 31 | } 32 | 33 | @Override 34 | public boolean verifyThreadsStopped() { 35 | return true; 36 | } 37 | 38 | @Override 39 | public void waitThreadsStopped() { 40 | } 41 | 42 | @Override 43 | public void tellThreadsToStop() { 44 | } 45 | 46 | @Override 47 | public void stop() { 48 | } 49 | 50 | @Override 51 | public void threadFinished(JMeterThread thread) { 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /jmeter-java-dsl-wrapper/src/test/java/us/abstracta/jmeter/javadsl/wrapper/customelements/MyThreadGroupGui.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.wrapper.customelements; 2 | 3 | import org.apache.jmeter.testelement.TestElement; 4 | import org.apache.jmeter.threads.gui.AbstractThreadGroupGui; 5 | 6 | public class MyThreadGroupGui extends AbstractThreadGroupGui { 7 | 8 | @Override 9 | public String getLabelResource() { 10 | return null; 11 | } 12 | 13 | @Override 14 | public TestElement createTestElement() { 15 | MyThreadGroup ret = new MyThreadGroup(); 16 | modifyTestElement(ret); 17 | return ret; 18 | } 19 | 20 | @Override 21 | public void modifyTestElement(TestElement element) { 22 | configureTestElement(element); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /jmeter-java-dsl-wrapper/src/test/java/us/abstracta/jmeter/javadsl/wrapper/customelements/MyThreadGroupTestBean.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.wrapper.customelements; 2 | 3 | import org.apache.jmeter.control.LoopController; 4 | import org.apache.jmeter.testbeans.TestBean; 5 | 6 | public class MyThreadGroupTestBean extends MyThreadGroup implements TestBean { 7 | 8 | // overwrite it to avoid failing when jmeter tries to load properties into field 9 | @Override 10 | public void setSamplerController(LoopController c) { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /jmeter-java-dsl-wrapper/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/codegeneration/CodeSegment.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.codegeneration; 2 | 3 | import java.util.Collection; 4 | import java.util.Map; 5 | 6 | /** 7 | * Specifies part of code to be generated including common logic required byt different type of code 8 | * segments. 9 | * 10 | * @since 1.5 11 | */ 12 | public interface CodeSegment { 13 | 14 | String buildCode(String indent); 15 | 16 | Collection getStaticImports(); 17 | 18 | Collection getImports(); 19 | 20 | Map getMethodDefinitions(); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/codegeneration/Comment.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.codegeneration; 2 | 3 | import java.util.Collection; 4 | import java.util.Collections; 5 | import java.util.Map; 6 | 7 | /** 8 | * Allows specifying a comment to be added to generated code. 9 | *

10 | * This is particularly helpful when adding tips, warnings or any extra information to generated 11 | * code that needs attention/review. 12 | * 13 | * @since 1.5 14 | */ 15 | public class Comment implements CodeSegment { 16 | 17 | private final String body; 18 | 19 | public Comment(String body) { 20 | this.body = body; 21 | } 22 | 23 | @Override 24 | public String buildCode(String indent) { 25 | return "// " + body; 26 | } 27 | 28 | @Override 29 | public Collection getStaticImports() { 30 | return Collections.emptyList(); 31 | } 32 | 33 | @Override 34 | public Collection getImports() { 35 | return Collections.emptyList(); 36 | } 37 | 38 | @Override 39 | public Map getMethodDefinitions() { 40 | return Collections.emptyMap(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/codegeneration/Indentation.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.codegeneration; 2 | 3 | /** 4 | * Handles code indentation logic. 5 | *

6 | * This class is currently not used instead of String in MethodCalls and MethodParams APIs to avoid 7 | * introducing non backwards compatible changes. 8 | * 9 | * @since 1.3 10 | */ 11 | public class Indentation { 12 | 13 | public static final String INDENT = " "; 14 | 15 | public static String indentLevel(int level) { 16 | StringBuilder ret = new StringBuilder(); 17 | for (int i = 0; i < level; i++) { 18 | ret.append(INDENT); 19 | } 20 | return ret.toString(); 21 | } 22 | 23 | public static String indent(String str, String indentation) { 24 | return indentation + str.replace("\n", "\n" + indentation); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/codegeneration/MethodCallBuilderRegistry.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.codegeneration; 2 | 3 | import java.util.Optional; 4 | 5 | public interface MethodCallBuilderRegistry { 6 | 7 | T findBuilderByClass(Class builderClass); 8 | 9 | Optional findBuilderMatchingContext(MethodCallContext methodCallContext); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/codegeneration/params/BoolParam.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.codegeneration.params; 2 | 3 | /** 4 | * Is a parameter with a boolean (true/false) value. 5 | * 6 | * @since 0.45 7 | */ 8 | public class BoolParam extends FixedParam { 9 | 10 | public BoolParam(String expression, Boolean defaultValue) { 11 | super(boolean.class, 12 | expression != null && expression.isEmpty() ? Boolean.FALSE.toString() : expression, 13 | us.abstracta.jmeter.javadsl.codegeneration.params.BoolParam::parseBool, defaultValue); 14 | } 15 | 16 | public BoolParam(Boolean value, Boolean defaultValue) { 17 | super(boolean.class, value, defaultValue); 18 | } 19 | 20 | private static Boolean parseBool(String value) { 21 | if (!String.valueOf(true).equals(value) && !String.valueOf(false).equals(value)) { 22 | throw new IllegalArgumentException(); 23 | } 24 | return Boolean.valueOf(value); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/codegeneration/params/DoubleParam.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.codegeneration.params; 2 | 3 | /** 4 | * Is a parameter with a double value. 5 | * 6 | * @since 0.61 7 | */ 8 | public class DoubleParam extends FixedParam { 9 | 10 | public DoubleParam(String expression, Double defaultValue) { 11 | super(double.class, expression, Double::valueOf, defaultValue); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/codegeneration/params/DynamicParam.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.codegeneration.params; 2 | 3 | import java.util.regex.Pattern; 4 | import us.abstracta.jmeter.javadsl.codegeneration.MethodParam; 5 | 6 | /** 7 | * Is a parameter with no fixed value (ie: a variable or jmeter function reference). 8 | * 9 | * @since 0.57 10 | */ 11 | public class DynamicParam extends MethodParam { 12 | 13 | private static final Pattern DYNAMIC_VALUE_PATTERN = Pattern.compile(".*\\$\\{.+}.*"); 14 | 15 | public DynamicParam(String expression) { 16 | super(String.class, expression); 17 | } 18 | 19 | public static boolean matches(String propVal) { 20 | return DYNAMIC_VALUE_PATTERN.matcher(propVal).matches(); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/codegeneration/params/EncodingParam.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.codegeneration.params; 2 | 3 | import java.nio.charset.Charset; 4 | import java.nio.charset.StandardCharsets; 5 | import java.util.Collections; 6 | import java.util.Map; 7 | import java.util.Set; 8 | import us.abstracta.jmeter.javadsl.codegeneration.MethodCall; 9 | 10 | /** 11 | * Is a parameter with an encoding (Charset) value. 12 | * 13 | * @since 0.62 14 | */ 15 | public class EncodingParam extends FixedParam { 16 | 17 | private static final Map STANDARD_CHARSETS_NAMES = 18 | findConstantNamesMap(StandardCharsets.class, Charset.class, s -> true); 19 | 20 | public EncodingParam(String expression, Charset defaultValue) { 21 | super(Charset.class, expression, Charset::forName, defaultValue); 22 | } 23 | 24 | @Override 25 | public Set getImports() { 26 | return Collections.singleton((STANDARD_CHARSETS_NAMES.get(value) != null 27 | ? StandardCharsets.class 28 | : Charset.class).getName()); 29 | } 30 | 31 | public String buildCode(String indent) { 32 | String standardCharsetName = STANDARD_CHARSETS_NAMES.get(value); 33 | return standardCharsetName != null 34 | ? StandardCharsets.class.getSimpleName() + "." + standardCharsetName 35 | : MethodCall.forStaticMethod(Charset.class, "forName", new StringParam(getValue().name())) 36 | .buildCode(); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/codegeneration/params/EnumParam.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.codegeneration.params; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collections; 5 | import java.util.Optional; 6 | import java.util.Set; 7 | import us.abstracta.jmeter.javadsl.codegeneration.params.EnumParam.EnumPropertyValue; 8 | 9 | /** 10 | * Is a parameter with an enum value. 11 | * 12 | * @param is the type of the enum value. 13 | * @since 0.62 14 | */ 15 | public class EnumParam & EnumPropertyValue> extends FixedParam { 16 | 17 | public EnumParam(Class paramType, String expression, T defaultValue) { 18 | super(paramType, expression, e -> parse(paramType, e), defaultValue); 19 | } 20 | 21 | private static & EnumPropertyValue> T parse(Class enumType, 22 | String propertyValue) { 23 | if (propertyValue.isEmpty()) { 24 | return null; 25 | } 26 | Optional ret = Arrays.stream(enumType.getEnumConstants()) 27 | .filter(v -> v.propertyValue().equals(propertyValue)) 28 | .findAny(); 29 | return ret.orElseThrow(() -> new IllegalArgumentException( 30 | "Unknown " + enumType.getSimpleName() + " property value: " + propertyValue)); 31 | } 32 | 33 | @Override 34 | public Set getImports() { 35 | return Collections.singleton(paramType.getName()); 36 | } 37 | 38 | @Override 39 | public String buildCode(String indent) { 40 | return paramType.getSimpleName() + "." + value.name(); 41 | } 42 | 43 | public interface EnumPropertyValue { 44 | 45 | String propertyValue(); 46 | 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/codegeneration/params/FixedParam.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.codegeneration.params; 2 | 3 | import java.util.function.Function; 4 | import us.abstracta.jmeter.javadsl.codegeneration.MethodParam; 5 | 6 | /** 7 | * Is a parameter with a fixed value. 8 | * 9 | * @param The type of the parameter value. 10 | * @since 0.57 11 | */ 12 | public abstract class FixedParam extends MethodParam { 13 | 14 | protected final T value; 15 | protected final T defaultValue; 16 | 17 | protected FixedParam(Class paramType, String expression, Function parser, 18 | T defaultValue) { 19 | super(paramType, expression); 20 | this.value = this.expression != null ? parser.apply(expression) : null; 21 | this.defaultValue = defaultValue; 22 | } 23 | 24 | protected FixedParam(Class paramType, T value, T defaultValue) { 25 | super(paramType, value == null ? null : value.toString()); 26 | this.value = value; 27 | this.defaultValue = defaultValue; 28 | } 29 | 30 | @Override 31 | public boolean isDefault() { 32 | return super.isDefault() || defaultValue != null && defaultValue.equals(value); 33 | } 34 | 35 | /** 36 | * Gets the value associated to the parameter. 37 | * 38 | * @return the value. 39 | */ 40 | public T getValue() { 41 | return value; 42 | } 43 | 44 | @Override 45 | public String buildCode(String indent) { 46 | return String.valueOf(value); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/codegeneration/params/FloatParam.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.codegeneration.params; 2 | 3 | /** 4 | * Is a parameter with a float value. 5 | * 6 | * @since 0.63 7 | */ 8 | public class FloatParam extends FixedParam { 9 | 10 | public FloatParam(String expression, Float defaultValue) { 11 | super(float.class, expression, Float::valueOf, defaultValue); 12 | } 13 | 14 | @Override 15 | public String buildCode(String indent) { 16 | return super.buildCode(indent) + "f"; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/codegeneration/params/IntParam.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.codegeneration.params; 2 | 3 | /** 4 | * Is a parameter with an integer value. 5 | * 6 | * @since 0.45 7 | */ 8 | public class IntParam extends FixedParam { 9 | 10 | public IntParam(String expression, Integer defaultValue) { 11 | super(int.class, expression, Integer::valueOf, defaultValue); 12 | } 13 | 14 | public IntParam(int value) { 15 | super(int.class, value, null); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/codegeneration/params/LongParam.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.codegeneration.params; 2 | 3 | /** 4 | * Is a parameter with a long value. 5 | * 6 | * @since 0.45 7 | */ 8 | public class LongParam extends FixedParam { 9 | 10 | public LongParam(String expression, Long defaultValue) { 11 | super(long.class, expression, Long::valueOf, defaultValue); 12 | } 13 | 14 | public LongParam(long value) { 15 | super(long.class, value, null); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/codegeneration/params/NameParam.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.codegeneration.params; 2 | 3 | /** 4 | * Is a parameter associated to a test element name. 5 | *

6 | * This type of parameter has the special consideration that when names are set to default values, 7 | * then they can be ignored. 8 | * 9 | * @since 0.45 10 | */ 11 | public class NameParam extends StringParam { 12 | 13 | public NameParam(String name, String defaultName) { 14 | super(name, defaultName); 15 | } 16 | 17 | @Override 18 | public boolean isIgnored() { 19 | return isDefault(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/codegeneration/params/StringArrayParam.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.codegeneration.params; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.Collectors; 5 | 6 | public class StringArrayParam extends FixedParam { 7 | 8 | public StringArrayParam(String expression) { 9 | super(String[].class, expression, e -> e.split(","), null); 10 | } 11 | 12 | @Override 13 | public String buildCode(String indent) { 14 | return Arrays.stream(value) 15 | .map(s -> buildStringLiteral(s, indent)) 16 | .collect(Collectors.joining(", ")); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/codegeneration/params/StringParam.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.codegeneration.params; 2 | 3 | /** 4 | * Is a parameter with a string value. 5 | *

6 | * This implementation in particular takes care of proper escaping of characters for code 7 | * generation. 8 | * 9 | * @since 0.45 10 | */ 11 | public class StringParam extends FixedParam { 12 | 13 | public StringParam(String expression, String defaultValue) { 14 | super(String.class, expression, v -> v, defaultValue); 15 | } 16 | 17 | public StringParam(String value) { 18 | this(value, null); 19 | } 20 | 21 | @Override 22 | public String buildCode(String indent) { 23 | return buildStringLiteral(value == null ? "" : value, indent); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/DslJmeterEngine.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core; 2 | 3 | import java.io.IOException; 4 | import java.util.concurrent.TimeoutException; 5 | 6 | /** 7 | * Interface to be implemented by classes allowing to run a DslTestPlan in different engines. 8 | * 9 | * @since 0.2 10 | */ 11 | public interface DslJmeterEngine { 12 | 13 | /** 14 | * Runs the given test plan obtaining the execution metrics. 15 | *

16 | * This method blocks execution until the test plan execution ends. 17 | * 18 | * @param testPlan to run in the JMeter engine. 19 | * @return the metrics associated to the run. 20 | * @throws IOException when there is a problem with an IO operation. 21 | * @throws InterruptedException when the execution thread is interrupted. 22 | * @throws TimeoutException when some configured time out is reached. Each engine might define 23 | * a different set of timeouts. 24 | */ 25 | TestPlanStats run(DslTestPlan testPlan) 26 | throws IOException, InterruptedException, TimeoutException; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/DslTestElement.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core; 2 | 3 | import org.apache.jorphan.collections.HashTree; 4 | 5 | /** 6 | * Interface to be implemented by all elements composing a JMeter test plan. 7 | * 8 | * @since 0.1 9 | */ 10 | public interface DslTestElement { 11 | 12 | /** 13 | * Builds the JMeter HashTree for this TestElement under the provided tree node. 14 | * 15 | * @param parent the node which will be the parent for the created tree. 16 | * @param context context information which contains information shared by elements while building 17 | * the test plan tree (eg: adding additional items to test plan when a particular protocol element 18 | * is added). 19 | * @return The tree created under the parent node. 20 | * @since 0.17 21 | */ 22 | HashTree buildTreeUnder(HashTree parent, BuildTreeContext context); 23 | 24 | /** 25 | * Shows the test element in it's defined GUI in a popup window. 26 | * 27 | * This might be handy to visualize the element as it looks in JMeter GUI. 28 | * 29 | * @since 0.18 30 | */ 31 | void showInGui(); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/assertions/DslAssertion.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.assertions; 2 | 3 | import us.abstracta.jmeter.javadsl.core.testelements.MultiLevelTestElement; 4 | 5 | public interface DslAssertion extends MultiLevelTestElement { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/configs/BaseConfigElement.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.configs; 2 | 3 | import org.apache.jmeter.gui.JMeterGUIComponent; 4 | import us.abstracta.jmeter.javadsl.core.testelements.BaseTestElement; 5 | 6 | /** 7 | * Contains common logic for config elements defined by the DSL. 8 | * 9 | * @since 0.37 10 | */ 11 | public abstract class BaseConfigElement extends BaseTestElement implements DslConfig { 12 | 13 | protected BaseConfigElement(String name, Class guiClass) { 14 | super(name, guiClass); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/configs/DslConfig.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.configs; 2 | 3 | import us.abstracta.jmeter.javadsl.core.testelements.MultiLevelTestElement; 4 | 5 | public interface DslConfig extends MultiLevelTestElement { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/controllers/BaseController.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.controllers; 2 | 3 | import java.util.List; 4 | import org.apache.jmeter.gui.JMeterGUIComponent; 5 | import us.abstracta.jmeter.javadsl.core.testelements.TestElementContainer; 6 | import us.abstracta.jmeter.javadsl.core.threadgroups.BaseThreadGroup.ThreadGroupChild; 7 | 8 | /** 9 | * Contains common logic for logic controllers defined by the DSL. 10 | * 11 | * @since 0.25 12 | */ 13 | public abstract class BaseController> extends 14 | TestElementContainer implements DslController { 15 | 16 | protected BaseController(String name, Class guiClass, 17 | List children) { 18 | super(name, guiClass, children); 19 | } 20 | 21 | /** 22 | * Allows specifying children elements that are affected by this controller. 23 | *

24 | * This method is helpful to keep general controller settings at the beginning and specify 25 | * children at last. 26 | * 27 | * @param children set of elements to be included in the controller. This list is appended to any 28 | * children defined in controller builder method. 29 | * @return a new controller instance for further configuration or usage. 30 | * @since 1.0 31 | */ 32 | @Override 33 | public T children(ThreadGroupChild... children) { 34 | return super.children(children); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/controllers/DslController.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.controllers; 2 | 3 | import us.abstracta.jmeter.javadsl.core.threadgroups.BaseThreadGroup.ThreadGroupChild; 4 | 5 | public interface DslController extends ThreadGroupChild { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/controllers/DslProxyControl.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.controllers; 2 | 3 | import java.util.Collections; 4 | import org.apache.jmeter.protocol.http.proxy.ProxyControl; 5 | import us.abstracta.jmeter.javadsl.codegeneration.MethodCall; 6 | import us.abstracta.jmeter.javadsl.codegeneration.MethodCallContext; 7 | import us.abstracta.jmeter.javadsl.codegeneration.SingleTestElementCallBuilder; 8 | 9 | // This class is just added to ignore ProxyControl when converting jmx to code 10 | public class DslProxyControl { 11 | 12 | public static class CodeBuilder extends SingleTestElementCallBuilder { 13 | 14 | public CodeBuilder() { 15 | super(ProxyControl.class, Collections.emptyList()); 16 | } 17 | 18 | @Override 19 | protected MethodCall buildMethodCall(ProxyControl testElement, MethodCallContext context) { 20 | return MethodCall.emptyCall(); 21 | } 22 | 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/engines/AutoStoppedTestException.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.engines; 2 | 3 | /** 4 | * Thrown when a test plan execution has been stopped due to an autoStop condition. 5 | */ 6 | public class AutoStoppedTestException extends IllegalStateException { 7 | 8 | public AutoStoppedTestException(String message) { 9 | super(message); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/engines/BaseTestStopper.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.engines; 2 | 3 | import java.util.concurrent.atomic.AtomicReference; 4 | import org.apache.jmeter.testelement.AbstractTestElement; 5 | 6 | /** 7 | * Provides common logic for {@link TestStopper} implementations. 8 | */ 9 | public abstract class BaseTestStopper extends AbstractTestElement implements TestStopper { 10 | 11 | protected final AtomicReference stopMessage = new AtomicReference<>(); 12 | 13 | @Override 14 | public void stop(String message) { 15 | if (stopMessage.compareAndSet(null, message)) { 16 | stopTestExecution(); 17 | } 18 | } 19 | 20 | protected abstract void stopTestExecution(); 21 | 22 | public String getStopMessage() { 23 | return stopMessage.get(); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/engines/TestStopper.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.engines; 2 | 3 | import org.apache.jmeter.testelement.TestElement; 4 | 5 | /** 6 | * Allows to stop a test plan execution with a given message. 7 | *

8 | * This is used to stop test plans when auto stop condition is triggered. 9 | *

10 | * Each engine should provide a proper implementation of this interface. 11 | */ 12 | public interface TestStopper extends TestElement { 13 | 14 | void stop(String message); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/listeners/BaseListener.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.listeners; 2 | 3 | import org.apache.jmeter.gui.JMeterGUIComponent; 4 | import us.abstracta.jmeter.javadsl.core.testelements.BaseTestElement; 5 | 6 | public abstract class BaseListener extends BaseTestElement implements DslListener { 7 | 8 | protected BaseListener(String name, Class guiClass) { 9 | super(name, guiClass); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/listeners/DslListener.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.listeners; 2 | 3 | import us.abstracta.jmeter.javadsl.core.testelements.MultiLevelTestElement; 4 | 5 | public interface DslListener extends MultiLevelTestElement { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/listeners/autostop/AutoStopComparison.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.listeners.autostop; 2 | 3 | import java.util.function.BiFunction; 4 | 5 | public enum AutoStopComparison { 6 | LT("<", (v1, v2) -> v1.compareTo(v2) < 0), 7 | LTE("<=", (v1, v2) -> v1.compareTo(v2) <= 0), 8 | GT(">", (v1, v2) -> v1.compareTo(v2) > 0), 9 | GTE(">=", (v1, v2) -> v1.compareTo(v2) >= 0); 10 | 11 | private final String name; 12 | private final BiFunction comparator; 13 | 14 | AutoStopComparison(String name, BiFunction comparator) { 15 | this.name = name; 16 | this.comparator = comparator; 17 | } 18 | 19 | boolean compare(Comparable v1, Comparable v2) { 20 | return comparator.apply(v1, v2); 21 | } 22 | 23 | public String getName() { 24 | return name; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/listeners/autostop/AutoStopMetric.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.listeners.autostop; 2 | 3 | import java.util.function.Function; 4 | import org.apache.jmeter.samplers.SampleResult; 5 | 6 | public enum AutoStopMetric { 7 | SAMPLE_TIME("sample time", SampleResult::getTime), 8 | LATENCY("latency", SampleResult::getLatency), 9 | CONNECT_TIME("connect time", SampleResult::getConnectTime), 10 | SAMPLES("samples", res -> 1L), 11 | ERRORS("errors", res -> res.isSuccessful() ? 0L : 1L), 12 | SENT_BYTES("sent bytes", SampleResult::getSentBytes), 13 | RECEIVED_BYTES("received bytes", SampleResult::getBytesAsLong); 14 | 15 | private final String name; 16 | private final Function extractor; 17 | 18 | AutoStopMetric(String name, Function extractor) { 19 | this.name = name; 20 | this.extractor = extractor; 21 | } 22 | 23 | public long extractFrom(SampleResult result) { 24 | return extractor.apply(result); 25 | } 26 | 27 | public String getName() { 28 | return name; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/listeners/autostop/AutoStopTestBeanBeanInfo.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.listeners.autostop; 2 | 3 | import java.beans.PropertyDescriptor; 4 | import java.util.ArrayList; 5 | import java.util.Arrays; 6 | import org.apache.jmeter.testbeans.BeanInfoSupport; 7 | import org.apache.jmeter.testbeans.gui.TableEditor; 8 | import org.apache.jmeter.util.JMeterUtils; 9 | 10 | public class AutoStopTestBeanBeanInfo extends BeanInfoSupport { 11 | 12 | public AutoStopTestBeanBeanInfo() { 13 | super(AutoStopTestBean.class); 14 | PropertyDescriptor p = property("conditions"); 15 | p.setPropertyEditorClass(TableEditor.class); 16 | p.setValue(TableEditor.CLASSNAME, AutoStopConditionElement.class.getName()); 17 | String[] props = new String[]{"regex", "metric", "aggregation", "percentile", 18 | "aggregationResetPeriodSeconds", "comparison", "value", "holdsForSeconds"}; 19 | p.setValue(TableEditor.HEADERS, Arrays.stream(props) 20 | .map(prop -> JMeterUtils.getResString("autostop_" + prop)) 21 | .toArray(String[]::new)); 22 | p.setValue(TableEditor.OBJECT_PROPERTIES, props); 23 | p.setValue(NOT_UNDEFINED, Boolean.TRUE); 24 | p.setValue(DEFAULT, new ArrayList<>()); 25 | p.setValue(MULTILINE, Boolean.TRUE); 26 | property("regex"); 27 | //cannot mark this property as hidden since otherwise it wouldn't be serialized 28 | property("testStopper"); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/listeners/autostop/aggregators/AutoStopAggregator.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.listeners.autostop.aggregators; 2 | 3 | public interface AutoStopAggregator> { 4 | 5 | void add(long value); 6 | 7 | T getValue(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/listeners/autostop/aggregators/AverageAggregator.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.listeners.autostop.aggregators; 2 | 3 | public class AverageAggregator implements AutoStopAggregator { 4 | 5 | private double val; 6 | private long count; 7 | 8 | @Override 9 | public void add(long value) { 10 | count++; 11 | val = count == 1 ? value 12 | /* 13 | using this formula instead of (value * count-1 + value)/count, or keeping total and count 14 | and divide at end, to avoid overflow and reduce precision loss while working with big 15 | numbers 16 | */ 17 | : (double) value / count + this.val * ((double) (count - 1) / count); 18 | } 19 | 20 | @Override 21 | public Double getValue() { 22 | return val; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/listeners/autostop/aggregators/PerSecondAggregator.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.listeners.autostop.aggregators; 2 | 3 | import java.time.Clock; 4 | import java.time.Instant; 5 | 6 | public class PerSecondAggregator implements AutoStopAggregator { 7 | 8 | private final Clock clock; 9 | private final AverageAggregator delegate = new AverageAggregator(); 10 | private Instant nextSecond; 11 | private long countInSecond; 12 | 13 | public PerSecondAggregator(Clock clock) { 14 | this.clock = clock; 15 | this.nextSecond = clock.instant().plusSeconds(1); 16 | } 17 | 18 | @Override 19 | public void add(long value) { 20 | Instant now = clock.instant(); 21 | if (nextSecond.compareTo(now) > 0) { 22 | countInSecond++; 23 | return; 24 | } 25 | delegate.add(countInSecond); 26 | nextSecond = nextSecond.plusSeconds(1); 27 | while (nextSecond.compareTo(now) <= 0) { 28 | delegate.add(0L); 29 | nextSecond = nextSecond.plusSeconds(1); 30 | } 31 | countInSecond = 0; 32 | } 33 | 34 | @Override 35 | public Double getValue() { 36 | return delegate.getValue(); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/listeners/autostop/aggregators/PercentAggregator.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.listeners.autostop.aggregators; 2 | 3 | public class PercentAggregator implements AutoStopAggregator { 4 | 5 | private final AverageAggregator delegate = new AverageAggregator(); 6 | 7 | @Override 8 | public void add(long value) { 9 | delegate.add(value); 10 | } 11 | 12 | @Override 13 | public Double getValue() { 14 | return delegate.getValue() * 100; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/listeners/autostop/aggregators/PercentileAggregator.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.listeners.autostop.aggregators; 2 | 3 | import java.text.DecimalFormat; 4 | import org.apache.commons.math3.stat.descriptive.rank.PSquarePercentile; 5 | 6 | public class PercentileAggregator implements AutoStopAggregator { 7 | 8 | private final PSquarePercentile percentile; 9 | 10 | public PercentileAggregator(double percentile) { 11 | this.percentile = new PSquarePercentile(percentile); 12 | } 13 | 14 | @Override 15 | public void add(long value) { 16 | percentile.increment(value); 17 | } 18 | 19 | @Override 20 | public Long getValue() { 21 | return Math.round(percentile.getResult()); 22 | } 23 | 24 | public static String getName(double percentile) { 25 | return "percentile " + new DecimalFormat("#.##").format(percentile); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/listeners/autostop/aggregators/SimpleAggregator.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.listeners.autostop.aggregators; 2 | 3 | import java.util.function.BiFunction; 4 | 5 | public class SimpleAggregator> implements AutoStopAggregator { 6 | 7 | private final BiFunction reducer; 8 | private T value; 9 | 10 | public SimpleAggregator(BiFunction reducer) { 11 | this.reducer = reducer; 12 | } 13 | 14 | public void add(long value) { 15 | this.value = this.value != null ? reducer.apply(this.value, value) : (T) (Long) value; 16 | } 17 | 18 | public T getValue() { 19 | return value; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/postprocessors/DslPostProcessor.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.postprocessors; 2 | 3 | import us.abstracta.jmeter.javadsl.core.testelements.MultiLevelTestElement; 4 | 5 | public interface DslPostProcessor extends MultiLevelTestElement { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/postprocessors/DslVariableExtractor.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.postprocessors; 2 | 3 | import org.apache.jmeter.processor.gui.AbstractPostProcessorGui; 4 | import us.abstracta.jmeter.javadsl.core.testelements.DslScopedTestElement; 5 | 6 | /** 7 | * Contains common logic for post processors which extract some value into a variable. 8 | * 9 | * @since 0.28 10 | */ 11 | public abstract class DslVariableExtractor> extends 12 | DslScopedTestElement implements DslPostProcessor { 13 | 14 | protected String varName; 15 | protected int matchNumber = 1; 16 | protected String defaultValue; 17 | 18 | public DslVariableExtractor(String name, Class guiClass, 19 | String varName) { 20 | super(name, guiClass); 21 | this.varName = varName; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/preprocessors/DslPreProcessor.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.preprocessors; 2 | 3 | import us.abstracta.jmeter.javadsl.core.testelements.MultiLevelTestElement; 4 | 5 | public interface DslPreProcessor extends MultiLevelTestElement { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/samplers/DslSampler.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.samplers; 2 | 3 | import us.abstracta.jmeter.javadsl.core.threadgroups.BaseThreadGroup.ThreadGroupChild; 4 | 5 | public interface DslSampler extends ThreadGroupChild { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/stats/CountMetricSummary.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.stats; 2 | 3 | /** 4 | * Provides summary data for a set of count values. 5 | * 6 | * @since 0.37 7 | */ 8 | public class CountMetricSummary { 9 | 10 | private long val = 0; 11 | private long elapsedTimeMillis; 12 | 13 | /** 14 | * Updates collected summary data with given info. 15 | * @param inc contains the last value counted. 16 | * @param elapsedTimeMillis specifies the number of milliseconds since the count started. 17 | */ 18 | public void increment(long inc, long elapsedTimeMillis) { 19 | val += inc; 20 | this.elapsedTimeMillis = elapsedTimeMillis; 21 | } 22 | 23 | /** 24 | * Provides the average count per second for the given metric. 25 | */ 26 | public double perSecond() { 27 | return elapsedTimeMillis != 0 ? val / ((double) elapsedTimeMillis / 1000) : 0; 28 | } 29 | 30 | /** 31 | * Provides the total count (the sum). 32 | */ 33 | public long total() { 34 | return val; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/stats/TimeMetricSummary.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.stats; 2 | 3 | import java.time.Duration; 4 | 5 | /** 6 | * Provides summary data for a set of timing values. 7 | * 8 | * @since 0.37 9 | */ 10 | public interface TimeMetricSummary { 11 | 12 | /** 13 | * Gets the minimum collected value. 14 | */ 15 | Duration min(); 16 | 17 | /** 18 | * Gets the maximum collected value. 19 | */ 20 | Duration max(); 21 | 22 | /** 23 | * Gets the mean/average of collected values. 24 | */ 25 | Duration mean(); 26 | 27 | /** 28 | * Gets the median of collected values. 29 | *

30 | * The median is the same as percentile 50, and is the value for which 50% of the collected values 31 | * is smaller/greater. 32 | *

33 | * This value might differ from {@link #mean()} when distribution of values is not symmetric. 34 | */ 35 | Duration median(); 36 | 37 | /** 38 | * Gets the 90 percentile of samples times. 39 | *

40 | * 90% of samples took less or equal to the returned value. 41 | */ 42 | Duration perc90(); 43 | 44 | /** 45 | * Gets the 95 percentile of samples times. 46 | *

47 | * 95% of samples took less or equal to the returned value. 48 | */ 49 | Duration perc95(); 50 | 51 | /** 52 | * Gets the 99 percentile of samples times. 53 | *

54 | * 99% of samples took less or equal to the returned value. 55 | */ 56 | Duration perc99(); 57 | 58 | } 59 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/testelements/MultiLevelTestElement.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.testelements; 2 | 3 | import us.abstracta.jmeter.javadsl.core.DslTestPlan.TestPlanChild; 4 | import us.abstracta.jmeter.javadsl.core.samplers.BaseSampler.SamplerChild; 5 | import us.abstracta.jmeter.javadsl.core.threadgroups.BaseThreadGroup.ThreadGroupChild; 6 | 7 | /** 8 | * This is just a simple interface to avoid code duplication for test elements that apply at 9 | * different levels of a test plan (at test plan, thread group or as sampler child). 10 | * 11 | * @since 0.11 12 | */ 13 | public interface MultiLevelTestElement extends TestPlanChild, ThreadGroupChild, SamplerChild { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/testelements/TestElementContainer.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.testelements; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | import org.apache.jmeter.gui.JMeterGUIComponent; 7 | import org.apache.jorphan.collections.HashTree; 8 | import us.abstracta.jmeter.javadsl.core.BuildTreeContext; 9 | import us.abstracta.jmeter.javadsl.core.DslTestElement; 10 | import us.abstracta.jmeter.javadsl.core.DslTestPlan; 11 | 12 | /** 13 | * Abstracts logic for {@link DslTestElement} that can nest other test elements. 14 | * 15 | * @param is type of test elements that can be nested by this class. 16 | *

17 | * Check {@link DslTestPlan} for an example. 18 | * @since 0.1 19 | */ 20 | public abstract class TestElementContainer, 21 | C extends DslTestElement> extends BaseTestElement { 22 | 23 | protected final List children = new ArrayList<>(); 24 | 25 | protected TestElementContainer(String name, Class guiClass, 26 | List children) { 27 | super(name, guiClass); 28 | this.children.addAll(children); 29 | } 30 | 31 | @SuppressWarnings("unchecked") 32 | protected T children(C... children) { 33 | this.children.addAll(Arrays.asList(children)); 34 | return (T) this; 35 | } 36 | 37 | @Override 38 | public HashTree buildTreeUnder(HashTree parent, BuildTreeContext context) { 39 | HashTree ret = super.buildTreeUnder(parent, context); 40 | children.forEach(c -> context.buildChild(c, ret)); 41 | return ret; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/threadgroups/DslThreadGroup.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.threadgroups; 2 | 3 | import us.abstracta.jmeter.javadsl.core.DslTestPlan.TestPlanChild; 4 | 5 | public interface DslThreadGroup extends TestPlanChild { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/threadgroups/LoadTimeLine.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.threadgroups; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import javax.swing.JComponent; 6 | import us.abstracta.jmeter.javadsl.core.util.SingleSeriesTimelinePanel; 7 | 8 | public class LoadTimeLine { 9 | 10 | private final String name; 11 | private final String loadUnit; 12 | private final List timePoints = new ArrayList<>(); 13 | 14 | public LoadTimeLine(String name, String loadUnit) { 15 | this.name = name; 16 | this.loadUnit = loadUnit; 17 | } 18 | 19 | public void add(long timeMillis, double value) { 20 | timePoints.add(new TimePoint(timeMillis, value)); 21 | } 22 | 23 | public String getName() { 24 | return name; 25 | } 26 | 27 | public JComponent buildChart() { 28 | SingleSeriesTimelinePanel ret = new SingleSeriesTimelinePanel(loadUnit); 29 | for (TimePoint tp : timePoints) { 30 | ret.add(tp.timeMillis, tp.value); 31 | } 32 | return ret; 33 | } 34 | 35 | public long getMaxTime() { 36 | return timePoints.stream() 37 | .mapToLong(tp -> tp.timeMillis) 38 | .max() 39 | .orElse(0L); 40 | } 41 | 42 | private static class TimePoint { 43 | 44 | private final long timeMillis; 45 | private final double value; 46 | 47 | private TimePoint(long timeIncrMillis, double value) { 48 | this.timeMillis = timeIncrMillis; 49 | this.value = value; 50 | } 51 | 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/timers/BaseTimer.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.timers; 2 | 3 | import org.apache.jmeter.gui.JMeterGUIComponent; 4 | import us.abstracta.jmeter.javadsl.core.testelements.BaseTestElement; 5 | 6 | /** 7 | * Contains common logic for all timers. 8 | * 9 | * @since 0.62 10 | */ 11 | public abstract class BaseTimer extends BaseTestElement implements DslTimer { 12 | 13 | protected BaseTimer(String name, Class guiClass) { 14 | super(name, guiClass); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/timers/DslSynchronizingTimer.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.timers; 2 | 3 | import java.lang.reflect.Method; 4 | import java.util.List; 5 | import org.apache.jmeter.testbeans.gui.TestBeanGUI; 6 | import org.apache.jmeter.testelement.TestElement; 7 | import org.apache.jmeter.timers.SyncTimer; 8 | import us.abstracta.jmeter.javadsl.codegeneration.MethodCall; 9 | import us.abstracta.jmeter.javadsl.codegeneration.MethodCallContext; 10 | import us.abstracta.jmeter.javadsl.codegeneration.SingleTestElementCallBuilder; 11 | 12 | /** 13 | * Uses JMeter Synchronizing Timer to allow sending a batch of requests simultaneously to a system 14 | * under test. 15 | * 16 | * @since 1.17 17 | */ 18 | public class DslSynchronizingTimer extends BaseTimer { 19 | 20 | public DslSynchronizingTimer() { 21 | super("Synchronizing Timer", TestBeanGUI.class); 22 | } 23 | 24 | @Override 25 | protected TestElement buildTestElement() { 26 | return new SyncTimer(); 27 | } 28 | 29 | public static class CodeBuilder extends SingleTestElementCallBuilder { 30 | 31 | public CodeBuilder(List builderMethods) { 32 | super(SyncTimer.class, builderMethods); 33 | } 34 | 35 | @Override 36 | protected MethodCall buildMethodCall(SyncTimer testElement, MethodCallContext context) { 37 | return buildMethodCall(); 38 | } 39 | 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/timers/DslTimer.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.timers; 2 | 3 | import us.abstracta.jmeter.javadsl.core.testelements.MultiLevelTestElement; 4 | 5 | public interface DslTimer extends MultiLevelTestElement { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/java/us/abstracta/jmeter/javadsl/core/util/JmeterFunction.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.util; 2 | 3 | import java.util.Arrays; 4 | import java.util.Locale; 5 | import java.util.stream.Collectors; 6 | 7 | public class JmeterFunction { 8 | 9 | public static String from(String name, Object... args) { 10 | String argsString = args.length > 0 11 | ? "(" + Arrays.stream(args) 12 | /* 13 | Using US locale to avoid particular locales generating commas which break parsing of 14 | function 15 | */ 16 | .map(a -> a instanceof Double || a instanceof Float 17 | ? String.format(Locale.US, "%f", a) 18 | : a.toString().replace("\\", "\\\\").replace(",", "\\,")) 19 | .collect(Collectors.joining(",")) + ")" 20 | : ""; 21 | return "${" + name + argsString + "}"; 22 | } 23 | 24 | public static String var(String varName) { 25 | return from(varName); 26 | } 27 | 28 | public static String groovy(String script) { 29 | return from("__groovy", script); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/resources/TestClass.template.java: -------------------------------------------------------------------------------- 1 | ///usr/bin/env jbang "$0" "$@" ; exit $? 2 | /* 3 | These commented lines make the class executable if you have jbang installed by making the file 4 | executable (eg: chmod +x ./PerformanceTest.java) and just executing it with ./PerformanceTest.java 5 | */ 6 | {{dependencies}} 7 | 8 | {{staticImports}} 9 | 10 | {{imports}} 11 | 12 | public class PerformanceTest { 13 | {{methodDefinitions}} 14 | @Test 15 | public void test() throws IOException { 16 | TestPlanStats stats = {{testPlan}}.run(); 17 | assertThat(stats.overall().errorsCount()).isEqualTo(0); 18 | } 19 | 20 | /* 21 | This method is only included to make the test class self-executable. You can remove it when 22 | executing tests with maven, gradle, or some other tool. 23 | */ 24 | public static void main(String[] args) { 25 | SummaryGeneratingListener summaryListener = new SummaryGeneratingListener(); 26 | LauncherFactory.create() 27 | .execute(LauncherDiscoveryRequestBuilder.request() 28 | .selectors(DiscoverySelectors.selectClass(PerformanceTest.class)) 29 | .build(), 30 | summaryListener); 31 | TestExecutionSummary summary = summaryListener.getSummary(); 32 | summary.printFailuresTo(new PrintWriter(System.err)); 33 | System.exit(summary.getTotalFailureCount() > 0 ? 1 : 0); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/resources/default-dependencies.txt: -------------------------------------------------------------------------------- 1 | org.assertj:assertj-core:${assertj-core.version} 2 | org.junit.jupiter:junit-jupiter-engine:${junit.version} 3 | org.junit.platform:junit-platform-launcher:${junit-platform.version} -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/resources/default-imports.txt: -------------------------------------------------------------------------------- 1 | static org.assertj.core.api.Assertions.assertThat 2 | static us.abstracta.jmeter.javadsl.JmeterDsl.* 3 | 4 | java.io.IOException 5 | java.io.PrintWriter 6 | org.junit.jupiter.api.Test 7 | org.junit.platform.engine.discovery.DiscoverySelectors 8 | org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder 9 | org.junit.platform.launcher.core.LauncherFactory 10 | org.junit.platform.launcher.listeners.SummaryGeneratingListener 11 | org.junit.platform.launcher.listeners.TestExecutionSummary 12 | us.abstracta.jmeter.javadsl.core.TestPlanStats 13 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/main/resources/us/abstracta/jmeter/javadsl/core/listeners/autostop/AutoStopTestBeanResources.properties: -------------------------------------------------------------------------------- 1 | autostop_regex=regex 2 | autostop_metric=metric 3 | autostop_aggregation=aggregation 4 | autostop_percentile=perc 5 | autostop_aggregationResetPeriod=every 6 | autostop_comparison=cmp 7 | autostop_value=value 8 | autostop_holdsForSeconds=holds (secs) 9 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/java/com/github/caciocavallosilano/cacio/ctc/CTCGraphicsConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.github.caciocavallosilano.cacio.ctc; 2 | 3 | import com.github.caciocavallosilano.cacio.peer.managed.FullScreenWindowFactory; 4 | import java.awt.Dimension; 5 | import java.awt.GraphicsConfiguration; 6 | import java.awt.GraphicsDevice; 7 | import java.awt.Rectangle; 8 | import java.awt.geom.AffineTransform; 9 | import java.awt.image.ColorModel; 10 | 11 | /* 12 | * This code is copied from original cacio code but initializing transforms to avoid NPEs with 13 | * Darklaf. 14 | */ 15 | public class CTCGraphicsConfiguration extends GraphicsConfiguration { 16 | 17 | private CTCGraphicsDevice device; 18 | 19 | CTCGraphicsConfiguration(CTCGraphicsDevice dev) { 20 | device = dev; 21 | } 22 | 23 | @Override 24 | public GraphicsDevice getDevice() { 25 | return device; 26 | } 27 | 28 | @Override 29 | public ColorModel getColorModel() { 30 | return ColorModel.getRGBdefault(); 31 | } 32 | 33 | @Override 34 | public ColorModel getColorModel(int transparency) { 35 | return ColorModel.getRGBdefault(); 36 | } 37 | 38 | @Override 39 | public AffineTransform getDefaultTransform() { 40 | return new AffineTransform(); 41 | } 42 | 43 | @Override 44 | public AffineTransform getNormalizingTransform() { 45 | return new AffineTransform(); 46 | } 47 | 48 | @Override 49 | public Rectangle getBounds() { 50 | Dimension d = FullScreenWindowFactory.getScreenDimension(); 51 | return new Rectangle(0, 0, d.width, d.height); 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/java/us/abstracta/jmeter/javadsl/TestExecutionLogger.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl; 2 | 3 | import org.junit.platform.engine.TestExecutionResult; 4 | import org.junit.platform.launcher.TestExecutionListener; 5 | import org.junit.platform.launcher.TestIdentifier; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | public class TestExecutionLogger implements TestExecutionListener { 10 | 11 | private static final Logger LOG = LoggerFactory.getLogger(TestExecutionLogger.class); 12 | 13 | @Override 14 | public void executionStarted(TestIdentifier testIdentifier) { 15 | LOG.debug("Started test {}", testIdentifier.getDisplayName()); 16 | } 17 | 18 | @Override 19 | public void executionFinished(TestIdentifier testIdentifier, 20 | TestExecutionResult testExecutionResult) { 21 | LOG.debug("Ended test {}: {}", testIdentifier.getDisplayName(), testExecutionResult.getStatus()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/java/us/abstracta/jmeter/javadsl/core/controllers/DslOnceOnlyControllerTest.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.core.controllers; 2 | 3 | import org.junit.jupiter.api.Nested; 4 | import org.junit.jupiter.api.Test; 5 | import us.abstracta.jmeter.javadsl.JmeterDslTest; 6 | import us.abstracta.jmeter.javadsl.codegeneration.MethodCallBuilderTest; 7 | import us.abstracta.jmeter.javadsl.core.DslTestPlan; 8 | import us.abstracta.jmeter.javadsl.core.TestPlanStats; 9 | 10 | import static org.assertj.core.api.Assertions.assertThat; 11 | import static us.abstracta.jmeter.javadsl.JmeterDsl.*; 12 | 13 | public class DslOnceOnlyControllerTest extends JmeterDslTest { 14 | 15 | @Test 16 | public void shouldExecuteOnlyOneTimeWhenOnceOnlyControllerInPlan() throws Exception { 17 | TestPlanStats stats = testPlan( 18 | threadGroup(1, 10, 19 | onceOnlyController( 20 | httpSampler(wiremockUri) 21 | ) 22 | ) 23 | ).run(); 24 | assertThat(stats.overall().samplesCount()).isEqualTo(1); 25 | } 26 | 27 | @Nested 28 | public class CodeBuilderTest extends MethodCallBuilderTest { 29 | 30 | public DslTestPlan testPlanWithOnceOnlyController() { 31 | return testPlan( 32 | threadGroup(1, 1, 33 | onceOnlyController( 34 | httpSampler("http://localhost") 35 | ) 36 | ) 37 | ); 38 | } 39 | 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/java/us/abstracta/jmeter/javadsl/http/HttpHeadersTest.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.http; 2 | 3 | import static us.abstracta.jmeter.javadsl.JmeterDsl.*; 4 | 5 | import org.apache.http.entity.ContentType; 6 | import org.junit.jupiter.api.Nested; 7 | import us.abstracta.jmeter.javadsl.codegeneration.MethodCallBuilderTest; 8 | import us.abstracta.jmeter.javadsl.core.DslTestPlan; 9 | 10 | public class HttpHeadersTest { 11 | 12 | @SuppressWarnings("unused") 13 | @Nested 14 | public class CodeBuilderTest extends MethodCallBuilderTest { 15 | 16 | public DslTestPlan testPlanWithHeaders() { 17 | return testPlan( 18 | threadGroup(1, 1, 19 | httpHeaders() 20 | .header("Accept", "application/json") 21 | .header("X-My-Header", "my-value") 22 | .header("X-Other-Header", "") 23 | .contentType(ContentType.APPLICATION_JSON), 24 | httpSampler("http://localhost") 25 | ) 26 | ); 27 | } 28 | 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/java/us/abstracta/jmeter/javadsl/http/HttpResponseBuilder.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.http; 2 | 3 | import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; 4 | 5 | import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder; 6 | import java.util.Arrays; 7 | import java.util.stream.Collectors; 8 | import org.apache.http.entity.ContentType; 9 | import org.apache.jmeter.protocol.http.util.HTTPConstants; 10 | 11 | public class HttpResponseBuilder { 12 | 13 | private HttpResponseBuilder() { 14 | } 15 | 16 | public static ResponseDefinitionBuilder buildEmbeddedResourcesResponse(String... resourcesUrls) { 17 | return aResponse() 18 | .withHeader(HTTPConstants.HEADER_CONTENT_TYPE, ContentType.TEXT_XML.toString()) 19 | .withBody("" + 20 | Arrays.stream(resourcesUrls) 21 | .map(r -> "") 22 | .collect(Collectors.joining()) 23 | + ""); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/java/us/abstracta/jmeter/javadsl/http/JmeterUrlTest.java: -------------------------------------------------------------------------------- 1 | package us.abstracta.jmeter.javadsl.http; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import org.junit.jupiter.api.Test; 6 | import org.junitpioneer.jupiter.cartesian.CartesianTest; 7 | import org.junitpioneer.jupiter.cartesian.CartesianTest.Values; 8 | 9 | public class JmeterUrlTest { 10 | 11 | @CartesianTest 12 | public void shouldGetExpectedParameterizedUrlWhenBuildFromString( 13 | @Values(strings = {"https", "${protocol}"}) String protocol, 14 | @Values(strings = {"myservice.com", "${domain}", "${domain}.myservice.com"}) String host, 15 | @Values(strings = {"", "443", "${port}"}) String port, 16 | @Values(strings = {"", "/my/path", "/my/${path}", "/${path}"}) String path) { 17 | String urlString = buildUrlString(protocol, host, port, path); 18 | JmeterUrl url = JmeterUrl.valueOf(urlString); 19 | assertThat(url).isEqualTo(new JmeterUrl(protocol, host, port, path.isEmpty() ? "/" : path)); 20 | } 21 | 22 | private String buildUrlString(String protocol, String host, String port, String path) { 23 | return protocol + "://" + host + (port.isEmpty() ? "" : ":" + port) + path; 24 | } 25 | 26 | @Test 27 | public void shouldGetExpectedParameterizedUrlWhenBuildFromStringWithUniqueExpression() { 28 | String expression = "${path}"; 29 | assertThat(JmeterUrl.valueOf(expression)).isEqualTo( 30 | new JmeterUrl(null, null, null, expression)); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener: -------------------------------------------------------------------------------- 1 | us.abstracta.jmeter.javadsl.TestExecutionLogger 2 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/resources/codegeneration/DisabledElements.java: -------------------------------------------------------------------------------- 1 | testPlan( 2 | httpCache() 3 | .disable(), 4 | threadGroup(1, 1, 5 | httpSampler("http://myservice.com")//, 6 | //ifController("true", 7 | // httpSampler("http://myservice.com") 8 | //) 9 | ) 10 | ) -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/resources/codegeneration/SimpleTest.java: -------------------------------------------------------------------------------- 1 | testPlan( 2 | threadGroup(1, 3, 3 | httpSampler("http://localhost") 4 | .post("{\"var\":\"val\"}", ContentType.APPLICATION_JSON), 5 | httpSampler("http://localhost") 6 | ), 7 | jtlWriter("", "results.jtl") 8 | ) -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/resources/codegeneration/fragments/HttpSamplerDsl.java: -------------------------------------------------------------------------------- 1 | httpSampler("https://myservice.com") 2 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/resources/codegeneration/fragments/IfControllerDsl.java: -------------------------------------------------------------------------------- 1 | private DslIfController ifController() { 2 | return ifController("true", 3 | httpSampler("http://myservice.com") 4 | ); 5 | } -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/resources/codegeneration/fragments/TestFragmentMethodDsl.template.java: -------------------------------------------------------------------------------- 1 | private DslTestFragmentController {{methodName}}() { 2 | return fragment({{fragmentName}} 3 | httpSampler("https://myservice.com") 4 | ); 5 | } -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/resources/codegeneration/fragments/fragment.template.jmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | https://myservice.com 12 | GET 13 | true 14 | false 15 | true 16 | false 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/resources/codegeneration/fragments/http-sampler.jmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | https://myservice.com 10 | GET 11 | true 12 | false 13 | true 14 | false 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/resources/codegeneration/fragments/include-controller.template.jmx: -------------------------------------------------------------------------------- 1 | 2 | {{jmxPath}} 3 | 4 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/resources/codegeneration/fragments/module.jmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | Test Plan 4 | Test Plan 5 | Thread Group 6 | {{controllerName}} 7 | 8 | 9 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/resources/codegeneration/fragments/thread-group.template.jmx: -------------------------------------------------------------------------------- 1 | 2 | continue 3 | 4 | false 5 | 1 6 | 7 | 1 8 | 1 9 | false 10 | 11 | 12 | true 13 | 14 | 15 | {{children}} 16 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/resources/codegeneration/test-plan.template.jmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | false 7 | true 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | {{children}} 16 | 17 | 18 | true 19 | 20 | 21 | 22 | true 23 | true 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/resources/datasets/dataset-long.csv: -------------------------------------------------------------------------------- 1 | VAR 2 | val0 3 | val1 4 | val2 5 | val3 6 | val4 7 | val5 8 | val6 9 | val7 10 | val8 11 | val9 12 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/resources/datasets/dataset-with-alt-format.csv: -------------------------------------------------------------------------------- 1 | val1 "val2" 2 | "val,3" val4 3 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/resources/datasets/dataset-with-headers.csv: -------------------------------------------------------------------------------- 1 | VAR1,VAR2 2 | val1,"val2" 3 | "val,3",val4 4 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/resources/graphite/storage-schemas.conf: -------------------------------------------------------------------------------- 1 | # Schema definitions for Whisper files. Entries are scanned in order, 2 | # and first match wins. This file is scanned for changes every 60 seconds. 3 | # 4 | # Definition Syntax: 5 | # 6 | # [name] 7 | # pattern = regex 8 | # retentions = timePerPoint:timeToStore, timePerPoint:timeToStore, ... 9 | # 10 | # Remember: To support accurate aggregation from higher to lower resolution 11 | # archives, the precision of a longer retention archive must be 12 | # cleanly divisible by precision of next lower retention archive. 13 | # 14 | # Valid: 60s:7d,300s:30d (300/60 = 5) 15 | # Invalid: 180s:7d,300s:30d (300/180 = 3.333) 16 | # 17 | 18 | # Carbon's internal metrics. This entry should match what is specified in 19 | # CARBON_METRIC_PREFIX and CARBON_METRIC_INTERVAL settings 20 | [carbon] 21 | pattern = ^carbon\. 22 | retentions = 10s:6h,1m:90d 23 | 24 | # Changed this since for some reason when set to aggregate every 10 seconds, it only reports counts 25 | # as 1 per every 10 seconds instead of the actual value (as if sum aggregate was not working).1 26 | # Jmeter Graphite Listener sends metrics in every second. Additionally, is nice to have as much 27 | # granularity as possible. 28 | [default_1sec_for_7day] 29 | pattern = .* 30 | retentions = 1s:7d,1m:30d -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/resources/jtls/complete-jtl.template.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | HTTP/1.1 200 OK 5 | Matched-Stub-Id: {{\w+-\w+-\w+-\w+-\w+}} 6 | Vary: Accept-Encoding, User-Agent 7 | Transfer-Encoding: chunked 8 | 9 | Connection: keep-alive 10 | Content-Type: application/json; charset=UTF-8 11 | Content-Length: 13 12 | Host: localhost:{{\d+}} 13 | User-Agent: Apache-HttpClient/{{[\w\.]+}} (Java/{{[\w\.]+}}) 14 | 15 | Non-TEXT response data, cannot record: () 16 | 17 | 18 | POST 19 | {"var":"val"} 20 | http://localhost:{{\d+}}/ 21 | 22 | 23 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/resources/jtls/custom-sample-jtl.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Tested 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/resources/jtls/default-jtl.template.csv: -------------------------------------------------------------------------------- 1 | timeStamp,elapsed,label,responseCode,responseMessage,threadName,dataType,success,failureMessage,bytes,sentBytes,grpThreads,allThreads,URL,Latency,IdleTime,Connect 2 | {{\d+}},{{\d+}},HTTP Request,200,OK,Thread Group 1-1,,true,,142,{{\d+}},1,1,http://localhost:{{\d+}}/,{{\d+}},0,{{\d+}} -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/resources/jtls/jtl-with-custom-variable.template.csv: -------------------------------------------------------------------------------- 1 | timeStamp,elapsed,label,responseCode,responseMessage,threadName,dataType,success,failureMessage,bytes,sentBytes,grpThreads,allThreads,URL,Latency,IdleTime,Connect,"my_var" 2 | {{\d+}},{{\d+}},HTTP Request,200,OK,Thread Group 1-1,,true,,142,{{\d+}},1,1,http://localhost:{{\d+}}/,{{\d+}},0,{{\d+}},my_val -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/resources/rmi_keystore.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abstracta/jmeter-java-dsl/HEAD/jmeter-java-dsl/src/test/resources/rmi_keystore.jks -------------------------------------------------------------------------------- /jmeter-java-dsl/src/test/resources/sample.properties: -------------------------------------------------------------------------------- 1 | MY_PROP=MY_VAL 2 | --------------------------------------------------------------------------------