> OctoPerf load testing - Test startup process documentation page. What happens in the JMeter and K6 docker containers we create.

Source: https://api.octoperf.com/doc/runtime/test-startup-process/

# Test startup process

## Summary

As your test gets started, we will automatically create instances and inside them docker containers. 

Since there are a number of ways you can influence this startup process, we have taken the time to describe it here. As you will see most of them require adding files to the [files menu](https://api.octoperf.com/doc/design/edit-virtual-user/configuration/files/), but their order is important depending on your goal:

|   #    | Action name                                        | Description                                                  |
| :----: | -------------------------------------------------- | ------------------------------------------------------------ |
| **1**  | [downloadTestResources](#download-resources)       | Download zip of all files and unzip it in `/resources`       |
| **2**  | [copyCustomHosts](#custom-hosts-file)              | If there is a **hosts** file in `/resources` override system **hosts** file with it |
| **3**  | [downloadJMX](#download-jmx)                       | Download the JMX from OctoPerf backend                       |
| **4**  | [installUserProperties](#user-properties-file)     | Get the default `user.properties` file from OctoPerf backend |
| **5**  | [downloadJMeterPlugins](#download-plugins)         | Try to download Plugins from [jmeter-plugins.org](https://jmeter-plugins.org) |
| **6**  | [configureKerberos](#kerberos)                     | Copy **Kerberos** configuration files from `/resources` to `/bin` |
| **7**  | [copyCustomJars](#custom-jars)                     | Copy ***.jar** from `/resources` to `/lib/ext`               |
| **8**  | [initJmxMonitoring](#jmx-monitoring)               | Activate JMeter JVM internal monitoring                      |
| **9**  | [runUserScript "before-test"](#before-test-script) | If it exists, execute the **before-test.sh**                 |
| **10** | [processCsvFiles](#csv-splitting)                  | CSV file splitting process                                   |
| **11** | [rendezVous](#rendezvous)                          | Rendez-vous until all the JMeter containers are ready to get started |
| **12** | [startJMeter](#start-jmeter)                       | Execute allocated Threadgroup(s)                             |
| **13** | [stopJMeter](#stop-jmeter)                         | At the end of planned duration, send shutdown signal         |
| **14** | [uploadLogs](#upload-logs-and-jtls)                | Upload JMeter logs to OctoPerf backend                       |
| **15** | [uploadJtls](#upload-logs-and-jtls)                | Upload JTLs to  OctoPerf backend                             |
| **16** | [runUserScript "after-test"](#after-test-script)   | If it exists, execute the **after-test.sh**                  |

## Detailed process

### Download Resources

The very first step is to get the resources from the OctoPerf server. This is exactly the same service called by the [export VU](https://api.octoperf.com/doc/design/#virtual-users-list-actions) menu. 

Once the zip file is downloaded, it will be unzipped under `${JMETER_HOME}/resources`.

!!! note
    Some of the files will be used in the next steps and may be removed or copied in another folder.

### Custom hosts file

If the `/resources` folder contains a file named `hosts` we will copy that file over the operating system `hosts` file. This allow you to override the DNS automatically before the test even starts.

!!! warning
    The load generator needs access to [api.octoperf.com](https://api.octoperf.com) (or your own OctoPerf server), make sure not to override this DNS entry.

### Download JMX

During this step, we download the JMX file from the OctoPerf server. The file is named `scenario.jmx` and will be copied to `${JMETER_HOME}` folder. 

!!! warning
    Since it is the JMX that will be executed by JMeter later, tamper with it at your own risk.

### User properties file

By default we provide our own `user.properties` file to ensure optimal JMeter settings for the test.

In some situations it can be interesting to edit or [customize this property file](https://jmeter.apache.org/usermanual/properties_reference.html) for your own requirements. You can do this [through a before-test.sh script](https://api.octoperf.com/doc/design/edit-virtual-user/configuration/files/#edit-jmeter-settings), as you can see from this guide the changes will be applied [at a later stage](#before-test-script) and thus will override the default file.

### Download Plugins

By default, we try to download any plugin JAR file automatically from [jmeter-plugins.org](https://jmeter-plugins.org). To that end we use the [plugins manager](https://jmeter-plugins.org/wiki/PluginsManager/) automatic detection. This is a good way to avoid storing the plugin JAR files in the project since that could affect the test start time.

You may get an error message when you execute the test from an [On-Premise Agent](https://api.octoperf.com/doc/on-premise-agent/) that doesn't have access to internet:

```java
ERROR: java.lang.RuntimeException: Failed to perform cmdline operation: jmeter-plugins.org: Name or service not known
```

As it only impacts the download of the plugin, you can instead provide the JAR file and disregard this message.

Alternatively if you're running your own [OctoPerf On-Premise Infra](https://api.octoperf.com/doc/on-premise-infra/) you can [deactivate this step in the settings](https://api.octoperf.com/doc/on-premise-infra/configuration/#jmeter-plugins).

### Kerberos

Kerberos authentication requires additional configuration files:

- krb5.conf: To define the hosts and kdc,

- jaas.conf: Java authentication settings, you can find [more info on how to configure it here](https://docs.oracle.com/javase/7/docs/technotes/guides/security/jgss/tutorials/AcnOnly.html).

If these files are present, we will overwrite the default JVM files with them.

### Custom Jars

JMeter allows you to use your own custom JAR files in the same way you can use plugins. Any JAR file provided through the files menu will be automatically copied to `${JMETER_HOME}/lib/ext` so that JMeter loads it when it starts.

!!! note
    If you disabled the [Download plugins](#download-plugins) step and you are using a plugin, the plugin JAR files must be provided this way.

### JMX Monitoring

We automatically monitor the load generators during the test. This steps prepares the required configuration so that we can capture the JVM internal metrics while the load test executes. This step is very important otherwise there's no way to assess if the JVM is overloaded during the test.

!!! info
    The list of metrics is available on the [agent monitoring page](https://api.octoperf.com/doc/analysis/edit-bench-report/agent-monitoring/#jvm-monitoring).

### Before test script

The `before-test.sh` script offers a way to execute system commands before the test starts. If there's such a file present, we will execute it. This is a perfect way to tune the JMeter container before it gets started. There are many examples available on the [files menu page](https://api.octoperf.com/doc/design/edit-virtual-user/configuration/files/#script-examples).

The `before-test.sh` script is almost the last step before we start JMeter, which means it can override any previous change. But also for debugging purpose you can use it for instance to log the contents of another file to make sure it was properly copied.

After this step, the CSV will be split automatically according to our [splitting mechanism](https://api.octoperf.com/doc/design/edit-virtual-user/configuration/variables/csv/#csv-file-splitting), but here you can still override the CSV file with another one before that happens.

### Csv Splitting

We will split files that correspond to [CSV variables](https://api.octoperf.com/doc/design/edit-virtual-user/configuration/variables/csv/) configured on "shared". 

To ensure a set of unique values for each load generator, we give each one a unique number and the entire CSV file. We then proceed to do a [modulo](https://en.wikipedia.org/wiki/Modulo_operation) on the file on every load generator. After this, the load generator proceeds to pick the split that corresponds to its unique number.

### RendezVous

This is a critical step because here we wait for all the load generators to be ready before sending the start signal. Otherwise their start time may be slightly off and the load policy would not execute as planned. In general it is just a matter of a few seconds but they can make all the difference when you want to reproduce advanced behavior.

### Start JMeter

This is where the JMeter test actually starts and the [test status moves](https://api.octoperf.com/doc/analysis/test-status/) to `RUNNING`.

We will first execute the [setup thread group](https://api.octoperf.com/doc/runtime/edit-scenario/edit-user-profile/options/setup-teardown/), then the main thread group and finish with the teardown. At this point, the UI redirects the OctoPerf user to the [bench report page](https://api.octoperf.com/doc/analysis/edit-bench-report/) and starts displaying the live metrics.

On the load generator what happens is that our JMeter plugin sends the results to its OctoPerf server every 5 seconds by default. Results are sent over HTTPS, as described on the [On-Premise Agent](https://api.octoperf.com/doc/on-premise-agent/) page.

### Stop JMeter

When the test reaches `FINISHED` or `ABORTED`, we stop JMeter and proceed to the next step.

!!! info
    If you're curious, we've written a guide on all the [possible test ending events](https://api.octoperf.com/doc/analysis/test-status/#test-finished) here.

### Upload Logs and JTLs

Before we remove the docker container for good, we upload the relevant log files to the OctoPerf server. The JMeter logs are always uploaded, whereas [the JTLs are optional](https://api.octoperf.com/doc/runtime/edit-scenario/edit-user-profile/options/jmeter/#jtl). In the end they will be available in the report under the [test logs menu](https://api.octoperf.com/doc/analysis/edit-bench-report/test-logs/#jmeter-logs).

### After test script

And the last step before the docker container is completely removed is to execute the `after-test.sh` if there's one.

This is the perfect time to upload a local file to the OctoPerf server, in particular if you used this test to create a CSV file for another test. We even have a [script example](https://api.octoperf.com/doc/design/edit-virtual-user/configuration/files/#uploading-a-csv-to-test-logs) for this.

!!! warning
    After this step there will be nothing left of the load generators or the test aside from the results stored in our database and the files that have been uploaded to the test logs. **It is not possible to recover anything else afterwards**. Make sure to save anything you need with your after test script.

## K6 load generators

A user profile running a [K6 Virtual User](https://api.octoperf.com/doc/design/create-virtual-user/import-k6-scripts/) runs in a container of the `octoperf/k6` image, which holds the K6 binary and the OctoPerf agent that reads its metrics, but no JMeter. Its startup takes fewer steps:

|   #   | Step | Description |
| :---: | ---- | ----------- |
| **1** | Download the scripts | Download the scripts of the Virtual User, the files of the project and the generated [`octoperf.js`](https://api.octoperf.com/doc/design/edit-virtual-user/action-types/k6-actions/k6-variables/) module |
| **2** | [runUserScript "before-test"](#before-test-script) | If it exists, execute the **before-test.sh** |
| **3** | [processCsvFiles](#csv-splitting) | Split the CSV files of the CSV variables the scripts use |
| **4** | Prepare | Add the `.crt` files of the project to the trusted certificates, then check the scripts with `k6 archive`: a script that does not start fails the test here |
| **5** | [rendezVous](#rendezvous) | Rendez-vous until all the containers are ready to get started |
| **6** | Run K6 | `k6 run` the load of the user profile, on the share of the virtual users of this container |
| **7** | Upload logs | Upload the K6 log and, when the user profile [uploads it](https://api.octoperf.com/doc/runtime/edit-scenario/edit-user-profile/options/k6/#script), the raw CSV output `k6.csv` |
| **8** | [runUserScript "after-test"](#after-test-script) | If it exists, execute the **after-test.sh** |

!!! info
    The environment of K6 is built by OctoPerf, not inherited from the container: a variable that `before-test.sh` exports reaches the scripts only when its name starts with `OCTOPERF_`, as `__ENV.OCTOPERF_...`. The steps of JMeter that set up JMeter itself, its plugins, its JARs or its properties, do not apply, and neither does the `hosts` file: map hostnames to addresses with the `hosts` option of the script, and set up DNS resolution in the [Network](https://api.octoperf.com/doc/runtime/edit-scenario/edit-user-profile/options/k6/#network) settings of the user profile.
