# 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/https 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/current_architecture.jpg)
<div align="center">Fig 1. Q.A.D. Architecture</div>
The straightforward architecture is depicted in Figure 1.

It uses an HTTP/HTTPS 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 `evdev_input` module, which writes to [Linux Input Subsystem](https://www.kernel.org/doc/html/next/input/input_uapi.html) to perform the actual operation. `evdev_input` 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`. The backend grabs a screenshot from ILM 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.:
- ilmControl (you can get this by building [wayland-ivi-extension](https://github.com/COVESA/wayland-ivi-extension))
- glib-2.0
- libsoup-2.4
- libcjson

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
```
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:
- `--version`, or`-v`: print Q.A.D. version and exit.
- `--cert-file`, or `-c`: To specify the path to TLS certification file.
- `--key-file`, or `-k`: To specify the path to TLS private key file.
- `--port`, or `-p`: To specify the port Q.A.D. listen at.
- `--help`, or `-h`: print help message and exit.

If **both** `--cert-file` and `--key-file` are provided, then Q.A.D. will use HTTPS for communication, otherwise, HTTP will be used.

If `--port` is not provided, then Q.A.D. will choose a random port to listen to.

In conclusion, if your environment variables are set properly, you are fine with HTTP and don't have a preference for port number, then just do:
```shell
./qad
```
Ideally you will see this message in terminal：
```text
Listening on http://0.0.0.0:<port>/
Listening on http://[::]:<port>/

Waiting for requests...
```

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

`qad` supports both `HTTP` and `HTTPS`, but here we will use `HTTP` in the examples.

## 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).

# 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 and/or LD_LIBRARY_PATH.
   ./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.
