# Connector Loadtester

Loadtester is a tool that load tests a UXP connector using its services.

### Prerequisites

* Apache Jmeter 5.1.1+
* JmeterSoapSampler plugin for Jmeter - https://github.com/spinning10/JMeterSoapSampler/wiki
* Git

* PostgreSQL

* Jenkins

* Python 3.x

* Python plugins:
lxml
yaml
pathlib

### Installing

1. Setup connector and import the provided services.
2. Set up the PostgreSQL database.

First, open your terminal and type in:

```
sudo -u postgres psql
```

Then, once in the psql terminal, create your database, connect to it and create an user to manage that database:

```
create database <database name>;
\connect <database name>
CREATE ROLE <user> WITH SUPERUSER CREATEDB CREATEROLE LOGIN PASSWORD '<password>';
GRANT ALL PRIVILEGES ON <database name> TO <user>;

```

Now that you're connected to the database, copy paste the following into the psql terminal:

```
Create or replace function random_string(length integer) returns text as
$$
declare
  chars text[] := '{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}';
  result text := '';
  i integer := 0;
begin
  if length < 0 then
    raise exception 'Given length cannot be less than 0';
  end if;
  for i in 1..length loop
    result := result || chars[1+random()*(array_length(chars, 1)-1)];
  end loop;
  return result;
end;
$$ language plpgsql;

CREATE OR REPLACE FUNCTION random_bytea(bytea_length integer)
RETURNS bytea AS $body$
    SELECT decode(string_agg(lpad(to_hex(width_bucket(random(), 0, 1, 256)-1),2,'0') ,''), 'hex')
    FROM generate_series(1, $1);
$body$
LANGUAGE 'sql'
VOLATILE
SET search_path = 'pg_catalog';
```

3. Add a connection between your database and the connector (make sure the services use that connection). An example URL would be the following:

```
jdbc:postgresql://localhost/mydb
```

4. Create a new folder and a bare git repository inside it. Initialize a regular repository in loadTester, fill in the config.yml, run "jmeterConfSetup.py" (you only have to run it on startup to configure the UXP connector server you want to load tester) and then push the contents to the bare repository. Give jenkins permissions to the bare repository with "sudo chown jenkins <bare repo folder name> -R".
5. Copy the jenkinsJob folder to "/var/lib/jenkins/jobs/" (you can rename it to whatever you wish) and give Jenkins permissions to that folder with "sudo chown jenkins <foldername> -R". Then, go into Jenkins and reload configuration from disk via "manage Jenkins". Finally, configure the Git repository path and credentials of the job.
6. Build with parameters to see if it works. If it does, configure the interval of the tests in the project configurations in Jenkins.

## Running the tests

To configure which tests you want to run and with what parameters, edit the config.yml file and upload it as a parameter when running the build. Default duration and thread number parameters will be used when they are not specified for an individual test.
The "include" parameter determines whether to run the specified tests or not.

## Adding tests

When creating a new service, make sure to follow the naming format of (testname)+(IN/OUT).
If you want to add that test to the project, then add the appropriate function into "tests.py" and add its name into the call list in "loadTestRunner.py".

Template for tests.py:
```
def sizeattachmentOUT(threads, duration, size, graphBoolean):
    testname = "size_attachment_OUT_" + "Threads-" + str(threads) + "_Duration-" + str(duration) + "_size-" + str(size)
    newValues("sizeattachmentOUT", "v1", "size", str(size), 0, 0)
    results = runTest(threads, duration, "TestJMX/loadXML.jmx", testname)
    readResults(results, testname, graphBoolean)
	
# testname is used for results file name, graphs file name and graph title
# newValues(serviceCode, serviceVersion, serviceInputParameter, serviceInput, flatElements, nestedElements) replaces the elements in the XML according to what you choose,
# the flatElements & nestedElements are used for tests where you want to test sending many elements at once but for regular tests, keep them at 0.
# If you want to send a multipart message (use a service where the input is an attachment) then generate the appropriate content, save it as Attachment_File in the TestJMX folder,
# make sure it has "cid:1339838373853" as the input value and instead of running "loadXML.jmx", run "loadXMLattachment.jmx". 
```

## Deployment

The project gets built in Jenkins and the results are displayed in HTML. Before building, you are given an option whether to overwrite graphs or not. If you choose yes, the results of
the tests are saved for future graphs and updated for the current ones. If you choose no, then the results of the tests will be displayed in console output, however, they will not be saved or included in the graphs.

You are also given an option to upload a config.yml file (template provided in the project folder). After uploading the config.yml for one build, the following builds will continue using the same config.yml until another one is provided.

## Authors

* Hendrik Šuvalov - Intern
* Ilja Kromonov - Instructor
