// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

= Qpid Dispatch

image:https://github.com/apache/qpid-dispatch/actions/workflows/build.yaml/badge.svg[
"GitHub Actions"
link="https://github.com/apache/qpid-dispatch/actions/workflows/build.yaml"]
image:https://img.shields.io/travis/apache/qpid-dispatch.svg?logo=travisci[
"Travis",
link="https://travis-ci.com/apache/qpid-dispatch"]
image:https://img.shields.io/github/license/apache/qpid-dispatch.svg[
"License",
link="https://github.com/apache/qpid-dispatch/blob/main/LICENSE"]

Qpid Dispatch is a high-performance, lightweight AMQP 1.0 message router.
It provides flexible and scalable interconnect between any AMQP endpoints,
whether they be clients, brokers or other AMQP-enabled services.

== Building and testing

NOTE: Dispatch will not build on Windows.

=== Dependencies

To build dispatch on a yum-based Linux system, you will need the following
packages installed:

- qpid-proton-c-devel
- python3-qpid-proton
- cmake
- make
- gcc
- python3-devel
- cyrus-sasl-plain
- cyrus-sasl-devel
- libnghttp2-devel
- asciidoc (for building docs)
- asciidoctor (for building docs)

To build formatted documentation (man pages, HTML, PDF) see the requirements in `doc/README.adoc`

=== Build

From the `qpid-dispatch` directory:

[source,shell script]
----
$ mkdir my_build    # or directory of your choice.
$ cd my_build
$ cmake ..
$ make
----

=== Running The Tests

From the `<build>` directory you can run all the system- and unit-tests with:
[source,shell script]
----
$ ctest -VV
----

ctest uses the script `<build>/test/run.py` to set up the correct environment for
tests. You can use it to run tests individually from the `<build>/tests`
directory.

.Example
[source,shell script]
----
$ ./run.py unit_tests_size 3
$ ./run.py -m unittest system_tests_qdstat
----

Run it without arguments to get a summary of how it can be used:
[source,shell script]
----
$ ./run.py
----

=== Test-only dependencies

The HTTP2 system tests (`tests/system_tests_http2.py`) use the Python Quart and hyper-h2 frameworks to start a HTTP2 server.
The HTTP2 system tests will run only if

1. Python version >= 3.7
2. Python Web Microframework Quart version >= 0.13
3. curl is available
4. hyper-h2 is available (pure-Python implementation of a HTTP/2 protocol stack)

The TCP system tests (tests/system_tests_tcp_adaptor.py) use the
Python selectors module when running echo clients and servers.
The TCP system tests run only if Python selectors is available.

.Install quart, h2 and selectors
[source,shell script]
----
pip3 install --user quart h2 selectors
----

Websocket system tests use the Python websockets asyncio module.

.Install websockets
[source,shell script]
----
pip3 install --user websockets
----

The gRPC system tests (tests/system_tests_grpc.py) use grpcio and protobuf modules.

.Install gRPC libraries
[source,shell script]
----
pip3 install --user grpcio protobuf
----

In order to regenerate the auto generated pb2 files used by system_tests_grpc.py,
you must also install the following dependency:

[source,shell script]
----
pip3 install --user grpcio-tools
----

And run the following command to generate grpc code:

[source,shell script]
----
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. ./friendship.proto
----

The system tests are implemented using Python's unittest library. This library is
used to run the tests by default. The tests can be also run using `xmlrunner` or `pytest`.
Pytest can generate a JUnit-compatible XML report containing an entry for each Python test method.
After running the tests, all XML reports will be found under tests/junitxmls in your build directory:

[source,shell script]
----
cmake .. -DPYTHON_TEST_COMMAND='-m;pytest;-vs;--junit-xml=junitxmls/${py_test_module}.xml;--pyargs;${py_test_module}'
----

=== Test Suite Code Coverage (GNU tools only)

Use coverage analysis to ensure that all code paths are exercised by
the test suite. To run the tests and perform code coverage analysis:

1. install the lcov package
[source,shell script]
$ yum install lcov

2. configure and build for the Coverage build type (from the <build> directory):
[source,shell script]
$ cmake -DCMAKE_BUILD_TYPE=Coverage .. && make

3. run the test suite and generate the coverage html output
[source,shell script]
$ ctest && make coverage

4. then point your browser at `<build>/coverage_results/html/index.html`

=== Clean build, install and test
[source]
----
$ source config.sh; test.sh
----

WARNING: Any preexisting directories 'build' and 'install' will be deleted.

This script then does the following:

- Do a fresh cmake and make in directory 'build'
- Run unit tests (not system tests) in 'build'
- Do 'make install' into the directory 'install'
- Run system tests on the installation in 'install'.

=== Run Time Validation

The CTest test suite can be configured to enable extra run time
validation checks against the dispatch router.

Since run time validation slows down qdrouter considerably it is
disabled by default.  It can be enabled by setting the RUNTIME_CHECK
build flag via the cmake command.

NOTE: Depending on your environment the ctest suite may time out
if validation is enabled due to the additional run time overhead it
adds.  You can extend the default test time via the ctest `--timeout`
option.

.Example
[source,shell script]
----
ctest --timeout 1500 -VV
----

The Qpid Dispatch Router test suite supports the following run time
validation tools:

==== Valgrind Memcheck
Runs qdrouterd under Valgrind's memcheck leak checker during the CTest
suite.  This will cause tests to fail if a memory error is
encountered.  Use the grinder tool (in the bin directory) to create a
summary of the errors found during the test run.

The valgrind toolset must be installed in order to use memcheck.

To enable memcheck set the RUNTIME_CHECK build flag to "memcheck":

[source,shell script]
----
cmake .. -DRUNTIME_CHECK=memcheck
----

If valgrind detects errors the qdrouterd process will exit with an
exit code of 42. This will be displayed in the CTest output. For
example:

[source]
----
RuntimeError: Errors during teardown:
Process XXXX error: exit code 42, expected 0
----

==== GCC/Clang Thread Sanitizer (TSAN)
This option turns on extra run time threading verification.

NOTE: Applicable only to GCC versions >= 7.4 and Clang versions >= 6.0.

To enable the thread sanitizer set the RUNTIME_CHECK build flag to "tsan":

[source,shell script]
----
cmake .. -DRUNTIME_CHECK=tsan
----

The TSAN library (libtsan) must be installed in order to use this
option.

If threading violations are detected during the CTest suite the
qdrouterd process will exit with an exit code of 66. This will be
displayed in the CTest output. For example:

[source]
----
RuntimeError: Errors during teardown:
Process XXXX error: exit code 66, expected 0
----

False positives can be suppressed via the `tsan.supp` file in the tests
directory.

==== GCC/Clang Address Sanitizer (ASAN)

This option turns on extra run time memory verification, including
leak checks.

NOTE: Applicable only to GCC versions >= 5.4 and Clang versions >= 6.0.

To enable the address sanitizer set the RUNTIME_CHECK build flag to "asan":

[source,shell script]
----
cmake .. -DCMAKE_C_FLAGS=-DQD_MEMORY_DEBUG -DRUNTIME_CHECK=asan
----

On Aarch64, a hardware-assisted address sanitizer is enabled with "hwasan":

[source,shell script]
----
cmake .. -DCMAKE_C_FLAGS=-DQD_MEMORY_DEBUG -DRUNTIME_CHECK=hwasan
----

The ASAN (libasan) and UBSAN (libubsan) libraries must be installed in
order to use this option.

NOTE: Memory pool will produce false leak reports unless `QD_MEMORY_DEBUG`
is also defined.

False positive leak errors can be suppressed via the lsan.supp file in
the tests directory.


=== CMake Build Options

Use `cmake-gui` to explore the CMake build options available.
Existing build directory can be opened with `cmake-gui -S .. -B .`

|===
|CMake option| Description

|`-DCMAKE_BUILD_TYPE=`
|Dispatch defaults to building with the `RelWithDebInfo` CMake preset.
Other options include `Debug` (disables optimizations) and `Coverage`.

|`-DQD_ENABLE_ASSERTIONS=`
|Seting this to `ON` enables asserts irrespective of `CMAKE_BUILD_TYPE`.

|`-DQD_MEMORY_STATS=`
|Dispatch will track memory pool usage statistics if this is enabled.

|`-DCONSOLE_INSTALL=`
|Web console will not be built if this is set to `OFF`.

|`-DRUNTIME_CHECK=`
|Enables C/C++ runtime checkers.See "Run Time Validation" chapter above.

|`-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON`
|With CMake 3.9+, compiles the project with LTO (Link Time Optimization) enabled.
Older CMake will only honor this option with the Intel compiler on Linux.
|===
