# Gabeldorsche Certification Tests

[TOC]

## What is GD cert test

A core problem behind Bluetooth interoperability testing is testers' inability to
automate test operations on certain peripherals. For example, although an user
can automate API calls on Android with tools like
[SL4A](https://android.googlesource.com/platform/external/sl4a/) or ADB shell
commands, they often struggle with automating corresponding operations on
carkits, headsets, and smart watches. Even if they find a way to automatically
control one model of such peripheral device using device maker's tools or
self-developed after-market tools such as relays and robotic arms, such kind of
tool usually does not scale to other models of peripherals due to their
differences in physical user interfaces.

GD certification test framework comes into rescue. In
the framework, a common API is defined using a [gRPC](https://grpc.io/) protobuf
for profiles such as HFP, AVRCP and function groups like pairing, scanning, and
advertising. Everyone who wants to test their Bluetooth device implements an
**gRPC Facade Server** using this protobuf definition. This server executable is
responsible in gluing various gRPC based APIs with their device specific
automation hook through a **Device Specific Driver**. The server will then
expose an IP address and a port number to the test runner. A **Test Runner**
process will load and execute the actual test case and use the auto-generated
gRPC facade client APIs to interact with the device being tested. The following
diagram shows how the system could be configured:

![cert_test_architecture_drawing](./cert_test_architecture_drawing.png)

## Terminology

**gRPC Facade**
:   A set of automation APIs of a specific profile (HFP, AVRCP, etc) or function
    group (pairing, scanning, advertising, etc) defined in gRPC protobuf format.

**Test Runner**
:   A process that loads and runs the actual test cases and use auto-generated
    gRPC facade client library to interact with test devices. Currently, the
    preferred test runner is the [Android ACTS](https://android.googlesource.com/platform/tools/test/connectivity/+/refs/heads/master/acts/)
    framework and test cases are written in Python for fast iteration and easy debugging

**gRPC Facade Server**
:   A concrete implementation of the gRPC automation APIs, which will convert
    RPC requests into invocations of device specific automation hook using a
    **Device Specific Driver**. This server can be written in any language and
    on any platform. The server need to expose an IP address and 3 ports

**Tester Signal Port**
:   A port to indicate that the server is ready for operation to the **Test
    Runner**

**gRPC Root Server Port**
:   A port that allows **Test Runner** to start and stop various functional
    facade services

**gRPC Facade Server Port**
:   A port that allows **Test Runner** to interact with actual profile
    implementations on the test device

**Device Specific Driver**
:   A library or some mechanism that allows the **gRPC Facade Server** to
    control the test device. This library is opaque to the **Test Runner** that
    should have no knowledge of how this component works * **Root-Canal**: A
    Bluetooth PHY emulator that takes either LMP or HCI packets. The goal is for
    this emulator to simulate a Physical RF environment without using any real
    Bluetooth adatper.

## How to run GD cert test in Android tree

Assume user has an Android checkout and finished `source build/envsetup.sh` and
`lunch` to a preferred target

### Run GD cert tests on host machine

```shell
$ANDROID_BUILD_TOP/packages/modules/Bluetooth/system/gd/cert/run --host
```

#### Python 3.8+
The cert tests require >python3.8 to operate and the associated python
virtualenv package.  The script may help properly install these requisites.

```shell
source $ANDROID_BUILD_TOP/packages/modules/Bluetooth/system/gd/cert/set_up_virtualenv.sh
```

### Run GD cert tests on devices for the first time

Connect at least two Android devices and follow on-screen instructions after
running the following command

```shell
$ANDROID_BUILD_TOP/packages/modules/Bluetooth/system/gd/cert/set_up_and_run_device_cert.sh
```

### Run GD cert tests on devices for the second time and after

Keeping the same set of devices connected

```shell
$ANDROID_BUILD_TOP/packages/modules/Bluetooth/system/gd/cert/run
```

### `packages/modules/Bluetooth/system/gd/cert/run` command reference

*   `--host`: Run tests on host only using `root-canal`
*   `--clean`: Remove any test setup files and do a clean test run
*   `--repeat=N`: Repeat running the same set of tests N times without redoing
    test setup
*   `--test_file=`: Running only tests listed in ``
*   `--test_filter=`: Test case filter in the format of
    "TestClass:test_case_name", for multiple test cases, quote them using " and
    separate each filter by space such as "TestClass1:test_case_1
    TestClass2:test_case_2"

### Run GD cert tests on devices over SSH

The following assumptions assume the following configuration

*   Local setup: Linux or MAC laptop with two Android phones connected
*   Remote setup: Linux or MAC workstation

1.  Check if your ADB version is up to date on both host machine and remote
    workstation. Both versions should be 29.0.3 or above. If not, uninstall and
    reinstall your adb.

1.  Enable SSH port forwarding for both ADB port and various ports used by our
    tests, run the following command on your Mac, assuming the following
    configuration {value=2}

    *   ADB Port: 5037
    *   Cert Device:
        *   gRPC Root Server Port: 8896
        *   gRPC Facade Port: 8898
        *   Signal Port: 8894
    *   Device Under Test:
        *   gRPC Root Server Port: 8897
        *   gRPC Facade Port: 8899
        *   Signal Port: 8895

    Among these ports, ADB Port needs to be forwarded from local machine to
    listen on remote workstation so that its adb client can connect to local
    machine's adb server (`ssh -R`). Signal Port needs to be forwarded from
    remote workstation to listen on local machine so that local phone can
    connect to Test Runner listening on this port during Facade Server bring up
    (`ssh -L`). Both gRPC Root Server Port and gRPC Facade Port need to be
    forwarded from local machine to listen on remote workstation so that Test
    Runner can connect to these ports on the Facade Server (`ssh -R`).

    Hence, the resulting `ssh` command is:

    ```shell
    ssh -R 5037:127.0.0.1:5037 -R 6401:127.0.0.1:6401 -R 6402:127.0.0.1:6402 \
    -R 6403:127.0.0.1:6403 -L 8894:127.0.0.1:8894 -L 8895:127.0.0.1:8895 \
    -R 8896:127.0.0.1:8896 -R 8897:127.0.0.1:8897 -R 8898:127.0.0.1:8898 \
    -R 8899:127.0.0.1:8899 
    ```

1.  Connect all your devices, open a different terminal on your Mac and run

    ```shell
    adb kill-server && adb devices
    ```

    You should see devices on your local machine shows up

1.  SSH into your remote workstation and run

    ```shell
    adb kill-server && adb devices
    ```

    You should see same set of devices connected to your local machine

1.  Continue with device setup

    ```shell
    $ANDROID_BUILD_TOP/packages/modules/Bluetooth/system/gd/cert/set_up_and_run_device_cert.sh
    ```

1.  In subsequent runs

    ```shell
    $ANDROID_BUILD_TOP/packages/modules/Bluetooth/system/gd/cert/run
    ```

## How to debug GD cert tests

Logs are produced and saved whenever GD cert tests runs. Depending on how the
tests were run, the log root is different

When running tests on local Android checkout, logs or most recent run are stored
at

*   /tmp/logs/HostOnlyCert/latest

Navigate test logs

In test root, the following logs are available:

*   In every directory layer:
    *   test_run_debug.txt: DEBUG level output from Python logging API
        scoped at their respective layer based on the directory
*   In test root directory:
    *   test_summary.json: A summary test results, including stack traces
        for any failures and metadata
    *   test_configs.json: The ACTs config used to run this test
    *   GdDevice_cert_stack_backing_process_coverage_summary.txt: code
        coverage summary from llvm-cov
*   In test class directory:
    *   rootcanal_logs.txt: Root-Canal stdout and stderrr, host test only
    *   Cert stack logs:
        *   GdDevice_cert_stack_backing_logs.txt: facade server process log
        *   cert_stack_btsnoop_hci.log: HCI packet log on cert device
        *   cert_stack_system_log: Android phone logcat output, device based
            test only
    *   Device under test logs:
        *   GdDevice_stack_under_test_backing_logs.txt: facade server
            process log
        *   stack_under_test_btsnoop_hci.log: HCI packet log on cert device
        *   stack_under_test_system_log: Android phone logcat output, device
            based test only
    *   Individual test directories: logs for individual test cases

## PTS test case coverage

A Python decorator is used to indicate a test's association with a Bluetooth SIG
Profile Tuning Suite (PTS) Qualification test. For example

```python
@metadata(
    pts_test_id="L2CAP/EXF/BV-01-C",
    pts_test_name="Extended Features Information Response for "
    "Enhanced Retransmission Mode")
```

These information can be found at the Test Case Reference List (TCRL) document
in
[Qualification Test Requirements](https://www.bluetooth.com/specifications/qualification-test-requirements/)
page at the Bluetooth SIG website.

## Code coverage

If the facade server binary is compiled using [`clang`](https://clang.llvm.org/)
and with
[`-fprofile-instr-generate -fcoverage-mapping`](https://clang.llvm.org/docs/SourceBasedCodeCoverage.html)
flags. A `.profraw` file will be generated in ech test class log directory after
the test run. The Test Runner will then try to index these profiling data using
[`llvm-profdata`](https://llvm.org/docs/CommandGuide/llvm-profdata.html),
iteratively merge them from each test class, and generate a line-by-line test
coverage report using
[`llvm-cov`](https://llvm.org/docs/CommandGuide/llvm-cov.html).