# Q.A.D. Introduction
Q.A.D. stands for Quality Assurance Daemon, a free software tool licensed under the MIT licence.

This is a simple, REST-API compliant daemon which makes automated testing on hardware possible by removing the need for physical intervention as Q.A.D allows inputs to be injected via http requests. This both eliminates the need to physically interact with the rig and allows for tasks to be carried out entirely automatically.

Q.A.D. can also take a screenshot and send it back to invoker. 

Also included in this repository is a generic os-autoinst backend for interaction with [OpenQA](http://open.qa/), so that Q.A.D. can be used to run OpenQA tests on hardware, which we'll refer to as 'rig' from now on. This is licensed under GPLv2 (same as OpenQA).

# Q.A.D. Architecture
![Q.A.D. Architecture](./images/architecture.jpg)
<div align="center">Fig 1. Q.A.D. Architecture</div>

Figure 1 shows Q.A.D. architecture at version `0.0.3`.

Q.A.D. uses an HTTP server to receive requests from an invoker. The server either passes the request JSON to JSON Parser, or directly handles screenshot parameter (more on this later).

For interactions like `touch`, `swipe`, and pressing a keyboard `button`, JSON Parser will parse the relevant parameters and feed them into `Input Backend`, which uses either `uinput` or `evdev_input` sub-module to write to [Linux Input Subsystem](https://www.kernel.org/doc/html/next/input/input_uapi.html) to perform the actual operation. `Input Backend` module reports back to the server if the desired operation succeeded or failed. 

For taking a screenshot, the server directly passes screen number to `Screenshot Backend`, which uses either `ILM` or `KMS` sub-module to grab the frame buffer, and sends it, or any error, back to the server.

Finally, the server tells the invoker whether the desired operation is successful or not.

# How to build Q.A.D.
You will need the following libraries to properly build Q.A.D.:
- libcjson
- libmicrohttpd
- libdrm
- libpng

Additionally, if you would like to build Q.A.D. with the `ilm` screen backend enabled, then you will need some extra libraries:
- ilmControl
- ilmCommon

you can get these by building [wayland-ivi-extension](https://github.com/COVESA/wayland-ivi-extension)

You will also need `meson` and `ninja` tool.

If all of those are available, then in project root dir, build Q.A.D. with:
```shell
./compile.sh
```
NB: if you do not want the `ilm` screen backend, then delete `-Dbackend-ilm=true` from `compile.sh`.

The compiled binary file should be located at `./qad`.

Note that your rig may use a different architecture than your build machine. You can check the compiled `qad` file architecture by: `file ./qad`.

# How to run Q.A.D.
Q.A.D. should run in the rig that you want to test, so the first thing you should do is send it to your target machine:
```shell
scp ./qad <username>@<rig_ip>:<target_directory>
```

Then, you might need to set some environment variables for your rig: 
```shell
XDG_RUNTIME_DIR=/run/user/<UID>
```

Currently, Q.A.D. uses the following command line arguments:
- `-h`, `--help`                    display this help
- `-p`, `--port` PORT               port to bind to
- `-i`, `--input-type` TYPE         uinput or evdev; defaults to uinput
- `-v`, `--version`                 display version
- `-s`, `--screen-backend` BACKEND  kms or ilm; defaults to kms
- `-k`, `--kms-backend-card` CARD   set DRM device; defaults to card0
- `-r`, `--kms-format-rgb`          use RGB pixel format instead of BGR

If `--port` is not provided, then Q.A.D. will use the default `8080` port.

In conclusion, if you are fine with all the default choices, then just do:
```shell
./qad
```
Ideally you will see this message in terminal：
```text
Using KMS backend
Starting QAD on port 8080
Running QAD, Enter q to quit
```

# How to communicate with Q.A.D.
Currently, Q.A.D. handles 4 endpoints, `/screen`, `/touch`, `/swipe`, and `/button`.

## Get screenshot
To get a screenshot out send a `GET` request to `/screen/N` where `N` is
the number of the screen to be captured.
e.g.
```
curl http://<rig-ip>:<port>/screen/2 --output <path/to/output/file>
```

## `touch` at `(x, y)`
To touch the screen at coordinate `(x, y)`, do a `POST` request to
`/touch` with the body being a JSON object of the form:

```
{
    x: int,
    y: int,
    duration: int,
    event: int
}
```
e.g.
```
curl -X POST -d '{"x": 0, "y": 0, "duration": 0, "event": 1}' http://<rig-ip>:<port>/touch
```

## `swipe` from `(x, y)` to `(x2, y2)`
To swipe the screen from coordinate `(x, y)` to `(x2, y2)`, do a `POST`
request to `/swipe` with the body being a JSON object of the form:

```
{
    x: int,
    y: int,
    x2: int,
    y2: int,
    velocity: int,
    event: int
}
```
e.g.
```
curl -X POST -d '{"x": 0, "y": 0, "x2": 100, "y2": 0, "velocity": 10, "event": 1}' http://<rig-ip>:<port>/swipe
```

## Press a keyboard `button`
To press a keyboard button, do a `POST` request to `/button` with the body being a JSON object of the form:
```
{
    value: int
    event: int
}
```
e.g.
```
curl -X POST -d '{"value": 1, "event": 1}' http://<rig-ip>:<port>/button # Press Esc key.
```
You can check the `value` for your desired key from `input-event-codes.h`, which is located at `<your_library_path>/linux/`.

## What is the `event` field
Q.A.D. imitates human input by writing to `/dev/input/event<N>`, `N` represents an input device id, you can get more info from [here](https://unix.stackexchange.com/questions/340430/dev-input-what-exactly-is-this).

When using the `uinput` input backend the following mappings are used:

* 0: Mouse input
* 1: Keyboard input
* 2: Touch input

# How to use Q.A.D. with OpenQA
1. Please first refer to OpenQA official [documentation](https://open.qa/docs/#_run_the_worker_container) for how to set up OpenQA worker and/or OpenQA server. You need to install our OpenQA backend as well by copying everything in `openqa` folder into your `os-autoinst` directory (e.g `/usr/lib64/os-autoinst/`). Note that our script needs some parameters to be set properly:
    - `QAD_SCREENNO=$screen_number`, the screen to capture.
    - `QAD_TOUCH_DEVICE_NO=$touch_number`, the device id to send input via.
    - `QAD_KEYBOARD_DEVICE_NO=$keyboard_number`, the keyboard event id.
    - `QAD_SERVER_ADDRESS=$rig_ip`, the full url of the running QAD daemon, (e.g. http://localhost:1234)
2. Create your OpenQA [tests](https://open.qa/docs/#_how_to_write_tests).
3. Run our Q.A.D.
   ```shell
   # Inside your rig.
   # You might need to properly set your environment variables first, like XDG_RUNTIME_DIR
   ./qad -p <port>
   ```
4. Start a job with the specified parameters.
   ```shell
   # Inside your OpenQA worker.
   openqa-cli api -X POST --host <server-name> jobs TEST=<test-suite> ARCH=<tested-arch> DISTRI=<tested-distri> FLAVOR=<tested-flavor> WORKER_CLASS=<openqa-worker-id> QAD_SERVER_ADDRESS=http://<qad-device-ip:qad_port> QAD_SCREEN=<screen-number> XRES=<screen-x-resolution> YRES=<screen-y-resolution> QAD_TOUCH_DEVICE_NO=<touch-input-device-number>
   ```
5. Now, you should be able to see the tests in your OpenQA server.

# Maintainers
Project maintainers are James Thomas (<james.thomas@codethink.co.uk>) and Scott Clarke (<scott.clarke@codethink.co.uk>), and they should approve all merge requests.

# License
There are two licenses in this repo. Q.A.D. itself is released under MIT license, however, inside `openqa` folder, the os-autoinst backend is released under GPL v2.
